Skip to content

Commit

Permalink
Progress #23: initial add of app site template
Browse files Browse the repository at this point in the history
aral committed Dec 14, 2021
1 parent a9825f5 commit 21ca6d5
Showing 11 changed files with 747 additions and 0 deletions.
17 changes: 17 additions & 0 deletions template/site/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# {APP.NAME} web site source

[![{APP.NAME} logo](128.svg)](https://{GITHUB.ORG.ORIGINAL}.github.io/{GITHUB.APP.ORIGINAL})

## [Visit the site.](https://{GITHUB.ORG.ORIGINAL}.github.io/{GITHUB.APP.ORIGINAL)

## Features:

- App name
- App description
- Screenshots (in progressively-enhanced, accessible carousel)
- Install button
- Commented-out Get It On AppCenter button
- Links to Help, Issues, and Funding
- [A signed Flatpak repository with static deltas](https://blogs.gnome.org/alexl/2017/02/10/maintaining-a-flatpak-repository/). The Install button links to the latest stable release of Comet from this repository.

__Work in progress:__ Running the `task/publish` script will publish the site to /docs so it can be used in GitHub pages.
12 changes: 12 additions & 0 deletions template/site/com.github.ORG.APP.flatpakref
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[Flatpak Ref]
Name=org.small_tech.comet
Url=https://comet.small-web.org/repo
Branch=stable
Title=Comet
Comment=Write better Git commit messages
Description=A distraction-free Git commit message editor with spell-check, first line character limit warnings, and emoji support.
Icon=https://comet.small-web.org/comet-128.svg
Homepage=https://comet.small-web.org
IsRuntime=false
RuntimeRepo=https://dl.flathub.org/repo/flathub.flatpakrepo
GPGKey=mQGNBGGwtGoBDACxT53XCAcnMMT4T3AaCg5XY1Ig5SJPrSuZc4so7CeUPayG1YyyvDJMtc4l6q6CFiWw9jXkVbWYEex1CTMq/qJAHWKV++lz/si3YzHchPa/NVLpA8oajabJa1mleAllb5Pi4i6IqXVjWoe74r39apXDZH15QQBaRMiZx+Quf4yDQbIpZO44+wsNbwqsOJYP60QLXMbOX/Xt/hy5ubG3PdEyhKHloS5recmCOzexDzDjDknVmNHM1OBxEQo7D3M7InP0NqOAQEixeMwmdyUX8Jt0bqSecrKQOcN1YeT1e2r/TfYD9dPpT0nMxKPHx+pXF+T9alMFMGREN98sa9vvjU8OFAP0ydSmMWICpU0UMysH7ZcfiP5G2KHyrX3cw6tse8s0aRT4Gu3zs0Gsrqse3YbC+DEWs721kD1gU6Gd+KGAMFs9m6cMDv4I8GskhUSVkITjH/7HvvPnpapcTtiBMTAdeVpB1YEbjFoajo4tia7rKU6YbNsSgvo8HoKrZUHGliMAEQEAAbQTYXJhbEBzbWFsbC10ZWNoLm9yZ4kBzgQTAQoAOBYhBFGnN6sZHjVmY9xw5TnVD3EUlFQMBQJhsLRqAhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEDnVD3EUlFQM4M8L/0XILyiUQvdJtmdGjV1AXKYj+4ZY+6Ybt5VUTqcywmP1oWRvmSTH9qUPHCBWFCcMJ6ZcltRf8OjXrLoZH+P5rNMEFA+MuzMtHaI30EvNyOjrRPXulOyYajMyBM+HIv3vYJ0Q/B+4DSLQmMj0GP58dHlWCgMQ2lTIec7sqdjjCVoQMTslLunEUTZWW8SSBT5MYNqtnt1wempVKb/dDquPIWtfitvDPLHLssPP3D+B33/IwQsuiiQneXCsb6BJ3qjc34Mzt6K3S74Ug5HBmp+fyHRIbsJJTF2gNwWsONpMAnLpmEgcCGbo7ej6+wRf8iMbcjaYyGO/b5jEcCVLuFxlv8fLDGrnN0gH0h4+XAX+C27ixBmaR3ZMJ8HQTTayx8nqKEEOW5EeWlB32hIBYJydPTj9sZmNPM6XBubvCYycs77HwJVJCOVxdoFq77WVXSo3FCINp0Q0oYG1OpJ63sH3FKUHoZmfwF+pFRLQqkLk2LrXiiCab6+/zEa0fpanj3DBDA==
30 changes: 30 additions & 0 deletions template/site/icons/browser-download-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions template/site/icons/bug-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions template/site/icons/help-contents-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions template/site/icons/io.elementary.appcenter-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions template/site/icons/positive-feedback-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions template/site/icons/text-x-copying-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
423 changes: 423 additions & 0 deletions template/site/index.css

Large diffs are not rendered by default.

104 changes: 104 additions & 0 deletions template/site/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<!doctype html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<title>{APP.NAME}: {APP.DESCRIPTION}</title>
<!-- Don’t have the browser request the favicon. -->
<link rel='icon' href='data:,'>
<link rel='stylesheet' href='index.css'>
</head>
<body>

<div id='content'>
<header>
<img id='icon' src='128.svg' alt='{APP.NAME} logo'>

<h1>{APP.NAME}</h1>

<p>{APP.DESCRIPTION}</p>
</header>

<!--
Progressively-enhanced carousel for screenshots.
For techniques used, see:
Super Simple Progressively Enhanced Carousel with CSS Scroll Snap (Marksu Oberlehner)
https://markus.oberlehner.net/blog/super-simple-progressively-enhanced-carousel-with-css-scroll-snap/
CSS-only carousel (Chris Coyier)
https://css-tricks.com/css-only-carousel/
-->
<section class='carousel' aria-label='Gallery'>
<div id='viewport'>
<div class='screenshot' id='screenshot1'>
<div class='content'>
<img src='https://raw.githubusercontent.com/{GITHUB.ORG.ORIGINAL}/{GITHUB.APP.ORIGINAL}/main/screenshots/en/light-and-dark.png' />
</div>
<div class='controls'>
<a class='previous' href='#screenshot5'>Wrap around to last screenshot</a>
<a class='next' href='#screenshot2'>Go to screenshot 2</a>
</div>
</div>

<div class='screenshot' id='screenshot2'>
<div class='content'>
<img src='https://raw.githubusercontent.com/{GITHUB.ORG.ORIGINAL}/{GITHUB.APP.ORIGINAL}/main/screenshots/en/light.png' />
</div>
<div class='controls'>
<a class='previous' href='#screenshot1'>Go to screenshot 1</a>
<a class='next' href='#screenshot3'>Go to screenshot 3</a>
</div>
</div>

<div class='screenshot' id='screenshot3'>
<div class='content'>
<img src='https://raw.githubusercontent.com/{GITHUB.ORG.ORIGINAL}/{GITHUB.APP.ORIGINAL}/main/screenshots/en/dark.png' />
</div>
<div class='controls'>
<a class='previous' href='#screenshot2'>Go to screenshot 2</a>
<a class='next' href='#screenshot1'>Wrap around to first screenshot</a>
</div>
</div>
</div>

<nav>
<ol>
<li><a href='#screenshot1'>Screenshot 1</a></li>
<li><a href='#screenshot2'>Screenshot 2</a></li>
<li><a href='#screenshot3'>Screenshot 3</a></li>
</ol>
</nav>

</section>

<section id='get-it'>
<a id='install' class='button' href='com.github.{GITHUB.ORG}.{GITHUB.APP}.flatpakref'><img src='icons/browser-download-symbolic.svg' alt=''>Install</a>

<!--
Uncomment this once your app has passed review if you have submitted it for the elementary OS AppCenter.
-->
<!--
<a id='get-it-on-appcenter' class='button' href='https://appcenter.elementary.io/com.github.{GITHUB.ORG}.{GITHUB.APP}'><img src='icons/io.elementary.appcenter-symbolic.svg' alt=''>Get it on AppCenter</a>
-->

<aside>Requires <a href='https://elementary.io/'>elementary OS 6</a>.</aside>
</section>

<footer>
<ul id='links'>
<li><a href='https://github.com/{GITHUB.ORG.ORIGINAL}/{GITHUB.APP.ORIGINAL}/#readme'>Help</a></li>
<li><a href='https://github.com/{GITHUB.ORG.ORIGINAL}/{GITHUB.APP.ORIGINAL}/issues'>Issues</a></li>
<!-- <li><a href='https://small-tech.org/fund-us'>Fund</a></li> -->
</ul>
<small id='info'>Made with <a href='https://github.com/small-tech/watson'>Watson</a>.</a></small>
<small id='copyright'>Copyright ⓒ {COPYRIGHT.YEAR}-present {COPYRIGHT.NAME}</small>
<small id='license'><img src='icons/text-x-copying-symbolic.svg' alt=''>Licensed under <a href='https://www.gnu.org/licenses/gpl-3.0.en.html'>GNU GPLv3</a>.</small>
</footer>
</div>

<script src='index.js'></script>
</div>
</body>
</html>
140 changes: 140 additions & 0 deletions template/site/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
//
// Calculate the current screenshot index based on the scroll position and viewport
// width of the carousel and use it to keep the same screenshot in view if
// the window is resized and also to display the currently-selected index
// in the navigation.
//

let currentScreenshotIndex = null
let transitioning = false

let navigationIndicators = null

function updateNavigationIndicators () {
let navigationIndicatorIndex = 0
navigationIndicators.forEach(navigationIndicator => {
if (navigationIndicatorIndex === currentScreenshotIndex) {
if (transitioning) {
navigationIndicator.className = 'transitioning'
} else {
navigationIndicator.className = 'selected'
}
} else {
navigationIndicator.className = ''
}
navigationIndicatorIndex++
})
}

function navigationClickHandler (event) {
const screenshot = document.querySelector(event.target.getAttribute('href'))
if (!screenshot) return

// Make sure page doesn’t jump vertically.
event.preventDefault()
screenshot.scrollIntoViewIfNeeded()

navigateToScreenshotAnchor(event.target)
}

function navigateToScreenshotAnchor (screenshotAnchor, transition = true) {
let requestedIndex

requestedIndex = Number(screenshotAnchor.toString().replace(/.*?screenshot/, '')) - 1

if (screenshotAnchor === '') {
requestedIndex = 0
transition = false
}

if (!transition) {
transitioning = false
currentScreenshotIndex = requestedIndex
updateNavigationIndicators()
return
}

if (requestedIndex !== currentScreenshotIndex) {
transitioning = true
currentScreenshotIndex = requestedIndex
updateNavigationIndicators()
}
}

window.addEventListener('resize', () => {
// Update the scroll position so the same Screenshot stays perfectly
// positioned within the carousel.
const viewport = document.getElementById('viewport')
viewport.scrollLeft = viewport.offsetWidth * currentScreenshotIndex
})

window.addEventListener('load', () => {

// Save references to the navigation indicators.
navigationIndicators = document.querySelectorAll('nav ol li a')

// Set the initial Screenshot based on the URL
navigateToScreenshotAnchor(window.location.hash, /* transition */ false)

// When a navigation indicator is clicked, we augment the default behaviour
// by updating the indicators to display the requested position with a dimmed
// indicator. When the transition is complete, our scroll event will pick it
// up and brighten the indicator.
navigationIndicators.forEach(navigationIndicator => {
navigationIndicator.addEventListener('click', navigationClickHandler)
})

// Also add the navigation indicator triggers to the arrow buttons.
const previousButtons = document.querySelectorAll('.screenshot .controls .previous')
const nextButtons = document.querySelectorAll('.screenshot .controls .next')

previousButtons.forEach(previousButton => {
previousButton.addEventListener('click', navigationClickHandler)
})

nextButtons.forEach(nextButton => {
nextButton.addEventListener('click', navigationClickHandler)
})

document.getElementById('viewport').addEventListener('scroll', event => {
const currentViewportWidth = event.target.offsetWidth
const currentViewportScrollPosition = event.target.scrollLeft

if (currentViewportScrollPosition % currentViewportWidth === 0) {
currentScreenshotIndex = currentViewportScrollPosition / currentViewportWidth
transitioning = false
updateNavigationIndicators()
}
})
})

// Polyfill for the non-standard yet actually useful scrollIntoViewIfNeeded method.
// (https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded)
// Courtesy: https://gist.github.com/hsablonniere/2581101
if (!Element.prototype.scrollIntoViewIfNeeded) {
Element.prototype.scrollIntoViewIfNeeded = function (centerIfNeeded) {
centerIfNeeded = arguments.length === 0 ? true : !!centerIfNeeded;

var parent = this.parentNode,
parentComputedStyle = window.getComputedStyle(parent, null),
parentBorderTopWidth = parseInt(parentComputedStyle.getPropertyValue('border-top-width')),
parentBorderLeftWidth = parseInt(parentComputedStyle.getPropertyValue('border-left-width')),
overTop = this.offsetTop - parent.offsetTop < parent.scrollTop,
overBottom = (this.offsetTop - parent.offsetTop + this.clientHeight - parentBorderTopWidth) > (parent.scrollTop + parent.clientHeight),
overLeft = this.offsetLeft - parent.offsetLeft < parent.scrollLeft,
overRight = (this.offsetLeft - parent.offsetLeft + this.clientWidth - parentBorderLeftWidth) > (parent.scrollLeft + parent.clientWidth),
alignWithTop = overTop && !overBottom;

if ((overTop || overBottom) && centerIfNeeded) {
parent.scrollTop = this.offsetTop - parent.offsetTop - parent.clientHeight / 2 - parentBorderTopWidth + this.clientHeight / 2;
}

if ((overLeft || overRight) && centerIfNeeded) {
parent.scrollLeft = this.offsetLeft - parent.offsetLeft - parent.clientWidth / 2 - parentBorderLeftWidth + this.clientWidth / 2;
}

if ((overTop || overBottom || overLeft || overRight) && !centerIfNeeded) {
this.scrollIntoView(alignWithTop);
}
};
}

0 comments on commit 21ca6d5

Please sign in to comment.