kopia lustrzana https://github.com/nolanlawson/pinafore
				
				
				
			start on instance theming
							rodzic
							
								
									eaaacdeef5
								
							
						
					
					
						commit
						f69797544d
					
				|  | @ -0,0 +1,58 @@ | |||
| #!/usr/bin/env node
 | ||||
| 
 | ||||
| const sass = require('node-sass') | ||||
| const chokidar = require('chokidar') | ||||
| const argv = require('yargs').argv | ||||
| const path = require('path') | ||||
| const debounce = require('lodash/debounce') | ||||
| const fs = require('fs') | ||||
| const pify = require('pify') | ||||
| const writeFile = pify(fs.writeFile.bind(fs)) | ||||
| const readdir = pify(fs.readdir.bind(fs)) | ||||
| const render = pify(sass.render.bind(sass)) | ||||
| 
 | ||||
| const globalScss = path.join(__dirname, '../scss/global.scss') | ||||
| const defaultThemeScss = path.join(__dirname, '../scss/themes/_default.scss') | ||||
| const globalCss = path.join(__dirname, '../assets/global.css') | ||||
| const scssDir = path.join(__dirname, '../scss') | ||||
| const themesScssDir = path.join(__dirname, '../scss/themes') | ||||
| const assetsDir = path.join(__dirname, '../assets') | ||||
| 
 | ||||
| function doWatch() { | ||||
|   chokidar.watch(scssDir).on('change', debounce(() => { | ||||
|     compileGlobalSass() | ||||
|     compileThemesSass() | ||||
|   }, 500)) | ||||
|   chokidar.watch() | ||||
| } | ||||
| 
 | ||||
| async function compileGlobalSass() { | ||||
|   let results = await Promise.all([ | ||||
|     render({file: defaultThemeScss}), | ||||
|     render({file: globalScss}) | ||||
|   ]) | ||||
| 
 | ||||
|   let css = results.map(_ => _.css).join('\n') | ||||
| 
 | ||||
|   await writeFile(globalCss, css, 'utf8') | ||||
| } | ||||
| 
 | ||||
| async function compileThemesSass() { | ||||
|   let files = (await readdir(themesScssDir)).filter(file => !path.basename(file).startsWith('_')) | ||||
|   await Promise.all(files.map(async file => { | ||||
|     let res = await render({file: path.join(themesScssDir, file)}) | ||||
|     await writeFile(path.join(assetsDir, path.basename(file).replace(/\.scss$/, '.css')), res.css, 'utf8') | ||||
|   })) | ||||
| } | ||||
| 
 | ||||
| async function main() { | ||||
|   await Promise.all([compileGlobalSass(), compileThemesSass()]) | ||||
|   if (argv.watch) { | ||||
|     doWatch() | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| Promise.resolve().then(main).catch(err => { | ||||
|   console.error(err) | ||||
|   process.exit(1) | ||||
| }) | ||||
										
											
												Plik diff jest za duży
												Load Diff
											
										
									
								
							
							
								
								
									
										10
									
								
								package.json
								
								
								
								
							
							
						
						
									
										10
									
								
								package.json
								
								
								
								
							|  | @ -6,13 +6,14 @@ | |||
|     "dev": "concurrently --kill-others \"npm run build-sass-watch\" \"node server.js\"", | ||||
|     "build": "npm run build-sass && sapper build", | ||||
|     "start": "cross-env NODE_ENV=production node server.js", | ||||
|     "build-sass": "node-sass scss -o assets", | ||||
|     "build-sass-watch": "npm run build-sass && node-sass -w scss -o assets", | ||||
|     "build-sass": "node ./bin/build-sass", | ||||
|     "build-sass-watch": "node ./bin/build-sass --watch", | ||||
|     "cy:run": "cypress run", | ||||
|     "cy:open": "cypress open", | ||||
|     "test": "run-p --race dev cy:run" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "chokidar": "^2.0.0", | ||||
|     "compression": "^1.7.1", | ||||
|     "concurrently": "^3.5.1", | ||||
|     "cross-env": "^5.1.3", | ||||
|  | @ -22,9 +23,11 @@ | |||
|     "font-awesome-svg-png": "^1.2.2", | ||||
|     "glob": "^7.1.2", | ||||
|     "idb": "^2.0.4", | ||||
|     "lodash": "^4.17.4", | ||||
|     "node-fetch": "^1.7.3", | ||||
|     "node-sass": "^4.7.2", | ||||
|     "npm-run-all": "^4.1.2", | ||||
|     "pify": "^3.0.0", | ||||
|     "sapper": "^0.3.1", | ||||
|     "serve-static": "^1.13.1", | ||||
|     "style-loader": "^0.19.1", | ||||
|  | @ -32,7 +35,8 @@ | |||
|     "svelte-loader": "^2.3.3", | ||||
|     "uglifyjs-webpack-plugin": "^1.1.5", | ||||
|     "url-search-params": "^0.10.0", | ||||
|     "webpack": "^3.10.0" | ||||
|     "webpack": "^3.10.0", | ||||
|     "yargs": "^10.1.1" | ||||
|   }, | ||||
|   "engines": { | ||||
|     "node": ">= 8" | ||||
|  |  | |||
|  | @ -0,0 +1,16 @@ | |||
| const themes = [ | ||||
|   { | ||||
|     name: 'default', | ||||
|     label: 'Royal (default)' | ||||
|   }, | ||||
|   { | ||||
|     name: 'scarlet', | ||||
|     label: 'Scarlet' | ||||
|   }, | ||||
|   { | ||||
|     name: 'hotpants', | ||||
|     label: 'Hotpants' | ||||
|   } | ||||
| ] | ||||
| 
 | ||||
| export { themes } | ||||
|  | @ -74,6 +74,14 @@ store.compute( | |||
|     }, loggedInInstances[currentInstance]) | ||||
| }) | ||||
| 
 | ||||
| store.compute( | ||||
|   'currentTheme', | ||||
|   ['currentInstance', 'instanceThemes'], | ||||
|   (currentInstance, instanceThemes) => { | ||||
|     return instanceThemes[currentInstance] || 'default' | ||||
|   } | ||||
| ) | ||||
| 
 | ||||
| if (process.browser && process.env.NODE_ENV !== 'production') { | ||||
|   window.store = store // for debugging
 | ||||
| } | ||||
|  |  | |||
|  | @ -15,20 +15,14 @@ | |||
|     </div> | ||||
|     <h2>Theme:</h2> | ||||
|     <form class="theme-chooser"> | ||||
|       {{#each themes as theme}} | ||||
|         <div class="theme-group"> | ||||
|         <input type="radio" name="current-theme" id="theme-default" value="default"> | ||||
|         <label for="theme-default">Royal (default)</label> | ||||
|       </div> | ||||
|       <div class="theme-group"> | ||||
|         <input type="radio" name="current-theme" id="theme-crimson" | ||||
|                value="crimson"> | ||||
|         <label for="theme-crimson">Crimson and Clover</label> | ||||
|       </div> | ||||
|       <div class="theme-group"> | ||||
|         <input type="radio" name="current-theme" id="theme-hotpants" | ||||
|                value="hotpants"> | ||||
|         <label for="theme-hotpants">Hot Pants</label> | ||||
|           <input type="radio" id="choice-theme-{{theme.name}}" | ||||
|                  value="{{theme.name}}" checked="$currentTheme === theme.name" | ||||
|                  bind:group="selectedTheme" on:change="onThemeChange()"> | ||||
|           <label for="choice-theme-{{theme.name}}">{{theme.label}}</label> | ||||
|         </div> | ||||
|       {{/each}} | ||||
|     </form> | ||||
|     {{/if}} | ||||
|   </SettingsLayout> | ||||
|  | @ -66,6 +60,7 @@ | |||
|   import Layout from '../../_components/Layout.html' | ||||
|   import SettingsLayout from '../_components/SettingsLayout.html' | ||||
|   import { getCurrentUser } from '../../_utils/mastodon/user' | ||||
|   import { themes } from '../../_static/themes' | ||||
| 
 | ||||
|   export default { | ||||
|     components: { | ||||
|  | @ -73,10 +68,26 @@ | |||
|       SettingsLayout | ||||
|     }, | ||||
|     store: () => store, | ||||
|     data: () => ({ | ||||
|       themes: themes | ||||
|     }), | ||||
|     oncreate: async function () { | ||||
|       let currentInstanceData = this.store.get('currentInstanceData') | ||||
|       let currentUser = await getCurrentUser(currentInstanceData.name, currentInstanceData.access_token) | ||||
|       this.set({currentUser: currentUser}) | ||||
|       this.set({ | ||||
|         currentUser: currentUser, | ||||
|         selectedTheme: this.store.get('currentTheme') | ||||
|       }) | ||||
|     }, | ||||
|     methods: { | ||||
|       onThemeChange () { | ||||
|         let newTheme = this.get('selectedTheme') | ||||
|         let instanceName = this.store.get('currentInstance') | ||||
|         let instanceThemes = this.store.get('instanceThemes') | ||||
|         instanceThemes[instanceName] = newTheme | ||||
|         this.store.set({instanceThemes: instanceThemes}) | ||||
|         this.store.save() | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | @ -1,11 +1,4 @@ | |||
| :root { | ||||
|   $main-theme-color: royalblue; // also: crimson, forestgreen, hotpink | ||||
|   $anchor-color: $main-theme-color; | ||||
|   $main-text-color: #333; | ||||
|   $border-color: #dadada; | ||||
|   $main-bg-color: white; | ||||
|   $secondary-text-color: white; | ||||
| 
 | ||||
| @mixin baseTheme() { | ||||
|   --button-primary-bg: lighten($main-theme-color, 7%); | ||||
|   --button-primary-text: $secondary-text-color; | ||||
|   --button-primary-border: darken($main-theme-color, 30%); | ||||
|  | @ -0,0 +1,12 @@ | |||
| $main-theme-color: royalblue; | ||||
| $anchor-color: $main-theme-color; | ||||
| $main-text-color: #333; | ||||
| $border-color: #dadada; | ||||
| $main-bg-color: white; | ||||
| $secondary-text-color: white; | ||||
| 
 | ||||
| @import "_base.scss"; | ||||
| 
 | ||||
| :root { | ||||
|   @include baseTheme() | ||||
| } | ||||
|  | @ -0,0 +1,12 @@ | |||
| $main-theme-color: hotpink; | ||||
| $anchor-color: $main-theme-color; | ||||
| $main-text-color: #333; | ||||
| $border-color: #dadada; | ||||
| $main-bg-color: white; | ||||
| $secondary-text-color: white; | ||||
| 
 | ||||
| @import "_base.scss"; | ||||
| 
 | ||||
| body.theme-hotpants { | ||||
|   @include baseTheme() | ||||
| } | ||||
|  | @ -0,0 +1,12 @@ | |||
| $main-theme-color: crimson; | ||||
| $anchor-color: $main-theme-color; | ||||
| $main-text-color: #333; | ||||
| $border-color: #dadada; | ||||
| $main-bg-color: white; | ||||
| $secondary-text-color: white; | ||||
| 
 | ||||
| @import "_base.scss"; | ||||
| 
 | ||||
| body.theme-crimson { | ||||
|   @include baseTheme() | ||||
| } | ||||
|  | @ -5,7 +5,6 @@ | |||
| 	<meta name="viewport" content="width=device-width, initial-scale=1"> | ||||
| 	<meta name='theme-color' content='#4169e1'> | ||||
| 
 | ||||
| 	<link rel='stylesheet' href='/theme-default.css'> | ||||
| 	<link rel='stylesheet' href='/global.css'> | ||||
| 	<link rel='manifest' href='/manifest.json'> | ||||
| 	<link rel='icon' type='image/png' href='/favicon.png'> | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 Nolan Lawson
						Nolan Lawson