forked from cybrespace/pinafore
		
	start on themes
This commit is contained in:
		
							parent
							
								
									fb9bc18edf
								
							
						
					
					
						commit
						eaaacdeef5
					
				
					 15 changed files with 222 additions and 97 deletions
				
			
		
							
								
								
									
										8
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -2881,10 +2881,10 @@
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "idb-keyval": {
 | 
					    "idb": {
 | 
				
			||||||
      "version": "2.3.0",
 | 
					      "version": "2.0.4",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-2.3.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/idb/-/idb-2.0.4.tgz",
 | 
				
			||||||
      "integrity": "sha1-TURLgMP4b8vNUTIbTcvJJHxZSMA="
 | 
					      "integrity": "sha512-Nw4ykKrrVje6YODRiRm/k2ucFEQeoY+zrkszfOuzVmxx8yyBMtZh2KLaRCKk9r5GzhuF0QlNCVjBewP2n5OZ7Q=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "ieee754": {
 | 
					    "ieee754": {
 | 
				
			||||||
      "version": "1.1.8",
 | 
					      "version": "1.1.8",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@
 | 
				
			||||||
    "extract-text-webpack-plugin": "^3.0.2",
 | 
					    "extract-text-webpack-plugin": "^3.0.2",
 | 
				
			||||||
    "font-awesome-svg-png": "^1.2.2",
 | 
					    "font-awesome-svg-png": "^1.2.2",
 | 
				
			||||||
    "glob": "^7.1.2",
 | 
					    "glob": "^7.1.2",
 | 
				
			||||||
    "idb-keyval": "^2.3.0",
 | 
					    "idb": "^2.0.4",
 | 
				
			||||||
    "node-fetch": "^1.7.3",
 | 
					    "node-fetch": "^1.7.3",
 | 
				
			||||||
    "node-sass": "^4.7.2",
 | 
					    "node-sass": "^4.7.2",
 | 
				
			||||||
    "npm-run-all": "^4.1.2",
 | 
					    "npm-run-all": "^4.1.2",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,11 +5,11 @@
 | 
				
			||||||
    </svg>
 | 
					    </svg>
 | 
				
			||||||
    <h1>Pinafore</h1>
 | 
					    <h1>Pinafore</h1>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
  <p>Pinafore is a web client for <a href="https://joinmastodon.org">Mastodon</a>, optimized for speed and simplicity.</p>
 | 
					  <p>Pinafore is a web client for <a rel="noopener" target="_blank" href="https://joinmastodon.org">Mastodon</a>, optimized for speed and simplicity.</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <p>To get started, <a href="/settings/instances/add">log in to an instance</a>.</p>
 | 
					  <p>To get started, <a href="/settings/instances/add">log in to an instance</a>.</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <p>Don't have an instance? <a href="https://joinmastodon.org">Join Mastodon!</a></p>
 | 
					  <p>Don't have an instance? <a rel="noopener" target="_blank" href="https://joinmastodon.org">Join Mastodon!</a></p>
 | 
				
			||||||
</FreeTextLayout>
 | 
					</FreeTextLayout>
 | 
				
			||||||
<style>
 | 
					<style>
 | 
				
			||||||
  .banner {
 | 
					  .banner {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,7 @@
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
  import { store } from '../_utils/store'
 | 
					  import { store } from '../_utils/store'
 | 
				
			||||||
  import { getHomeTimeline } from '../_utils/mastodon'
 | 
					  import { getHomeTimeline } from '../_utils/mastodon/oauth'
 | 
				
			||||||
  import fixture from '../_utils/fixture.json'
 | 
					  import fixture from '../_utils/fixture.json'
 | 
				
			||||||
  import Status from './Status.html'
 | 
					  import Status from './Status.html'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										27
									
								
								routes/_utils/ajax.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								routes/_utils/ajax.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,27 @@
 | 
				
			||||||
 | 
					export async function post(url, body) {
 | 
				
			||||||
 | 
					  return await (await fetch(url, {
 | 
				
			||||||
 | 
					    method: 'POST',
 | 
				
			||||||
 | 
					    headers: {
 | 
				
			||||||
 | 
					      'Accept': 'application/json',
 | 
				
			||||||
 | 
					      'Content-Type': 'application/json'
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    body: JSON.stringify(body)
 | 
				
			||||||
 | 
					  })).json()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function paramsString(paramsObject) {
 | 
				
			||||||
 | 
					  let params = new URLSearchParams()
 | 
				
			||||||
 | 
					  Object.keys(paramsObject).forEach(key => {
 | 
				
			||||||
 | 
					    params.set(key, paramsObject[value])
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  return params.toString()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export async function get(url, headers = {}) {
 | 
				
			||||||
 | 
					  return await (await fetch(url, {
 | 
				
			||||||
 | 
					    method: 'GET',
 | 
				
			||||||
 | 
					    headers: Object.assign(headers, {
 | 
				
			||||||
 | 
					      'Accept': 'application/json',
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  })).json()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,21 +0,0 @@
 | 
				
			||||||
import idbKeyVal from 'idb-keyval'
 | 
					 | 
				
			||||||
import { blobToBase64 } from '../_utils/binary'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
let databasePromise
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if (process.browser) {
 | 
					 | 
				
			||||||
  databasePromise = Promise.resolve().then(async () => {
 | 
					 | 
				
			||||||
    let token = await idbKeyVal.get('secure_token')
 | 
					 | 
				
			||||||
    if (!token) {
 | 
					 | 
				
			||||||
      let array = new Uint32Array(1028)
 | 
					 | 
				
			||||||
      crypto.getRandomValues(array);
 | 
					 | 
				
			||||||
      let token = await blobToBase64(new Blob([array]))
 | 
					 | 
				
			||||||
      await idbKeyVal.set('secure_token', token)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return idbKeyVal
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
} else {
 | 
					 | 
				
			||||||
  databasePromise = Promise.resolve()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export { databasePromise }
 | 
					 | 
				
			||||||
							
								
								
									
										2
									
								
								routes/_utils/database/database.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								routes/_utils/database/database.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					import keyval from './idb-keyval'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										57
									
								
								routes/_utils/database/idb-keyval.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								routes/_utils/database/idb-keyval.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,57 @@
 | 
				
			||||||
 | 
					import idb from 'idb'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// copypasta'd from https://github.com/jakearchibald/idb#keyval-store
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const dbPromise = idb.open('keyval-store', 1, upgradeDB => {
 | 
				
			||||||
 | 
					  upgradeDB.createObjectStore('keyval')
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const idbKeyval = {
 | 
				
			||||||
 | 
					  get(key) {
 | 
				
			||||||
 | 
					    return dbPromise.then(db => {
 | 
				
			||||||
 | 
					      return db.transaction('keyval').objectStore('keyval').get(key)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  set(key, val) {
 | 
				
			||||||
 | 
					    return dbPromise.then(db => {
 | 
				
			||||||
 | 
					      const tx = db.transaction('keyval', 'readwrite')
 | 
				
			||||||
 | 
					      tx.objectStore('keyval').put(val, key)
 | 
				
			||||||
 | 
					      return tx.complete
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  delete(key) {
 | 
				
			||||||
 | 
					    return dbPromise.then(db => {
 | 
				
			||||||
 | 
					      const tx = db.transaction('keyval', 'readwrite')
 | 
				
			||||||
 | 
					      tx.objectStore('keyval').delete(key)
 | 
				
			||||||
 | 
					      return tx.complete
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  clear() {
 | 
				
			||||||
 | 
					    return dbPromise.then(db => {
 | 
				
			||||||
 | 
					      const tx = db.transaction('keyval', 'readwrite')
 | 
				
			||||||
 | 
					      tx.objectStore('keyval').clear()
 | 
				
			||||||
 | 
					      return tx.complete
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  keys() {
 | 
				
			||||||
 | 
					    return dbPromise.then(db => {
 | 
				
			||||||
 | 
					      const tx = db.transaction('keyval')
 | 
				
			||||||
 | 
					      const keys = []
 | 
				
			||||||
 | 
					      const store = tx.objectStore('keyval')
 | 
				
			||||||
 | 
					      // This would be store.getAllKeys(), but it isn't supported by Edge or Safari.
 | 
				
			||||||
 | 
					      // openKeyCursor isn't supported by Safari, so we fall back
 | 
				
			||||||
 | 
					      const iterate = store.iterateKeyCursor || store.iterateCursor
 | 
				
			||||||
 | 
					      iterate.call(store, cursor => {
 | 
				
			||||||
 | 
					        if (!cursor) {
 | 
				
			||||||
 | 
					          return
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        keys.push(cursor.key)
 | 
				
			||||||
 | 
					        cursor.continue()
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return tx.complete.then(() => keys)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default idbKeyval
 | 
				
			||||||
| 
						 | 
					@ -1,62 +0,0 @@
 | 
				
			||||||
const WEBSITE = 'https://pinafore.social'
 | 
					 | 
				
			||||||
const REDIRECT_URI = (typeof location !== 'undefined' ? location.origin : 'https://pinafore.social') + '/settings/instances/add'
 | 
					 | 
				
			||||||
const SCOPES = 'read write follow'
 | 
					 | 
				
			||||||
const CLIENT_NAME = 'Pinafore'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function registerApplication(instanceName) {
 | 
					 | 
				
			||||||
  const url = `https://${instanceName}/api/v1/apps`
 | 
					 | 
				
			||||||
  return fetch(url, {
 | 
					 | 
				
			||||||
    method: 'POST',
 | 
					 | 
				
			||||||
    headers: {
 | 
					 | 
				
			||||||
      'Accept': 'application/json',
 | 
					 | 
				
			||||||
      'Content-Type': 'application/json'
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    body: JSON.stringify({
 | 
					 | 
				
			||||||
      client_name: CLIENT_NAME,
 | 
					 | 
				
			||||||
      redirect_uris: REDIRECT_URI,
 | 
					 | 
				
			||||||
      scopes: SCOPES,
 | 
					 | 
				
			||||||
      website: WEBSITE
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function generateAuthLink(instanceName, clientId) {
 | 
					 | 
				
			||||||
  let url = `https://${instanceName}/oauth/authorize`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  let params = new URLSearchParams()
 | 
					 | 
				
			||||||
  params.set('client_id', clientId)
 | 
					 | 
				
			||||||
  params.set('redirect_uri', REDIRECT_URI)
 | 
					 | 
				
			||||||
  params.set('response_type', 'code')
 | 
					 | 
				
			||||||
  params.set('scope', SCOPES)
 | 
					 | 
				
			||||||
  url += '?' + params.toString()
 | 
					 | 
				
			||||||
  return url
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function getAccessTokenFromAuthCode(instanceName, clientId, clientSecret, code) {
 | 
					 | 
				
			||||||
  let url = `https://${instanceName}/oauth/token`
 | 
					 | 
				
			||||||
  return fetch(url, {
 | 
					 | 
				
			||||||
    method: 'POST',
 | 
					 | 
				
			||||||
    headers: {
 | 
					 | 
				
			||||||
      'Accept': 'application/json',
 | 
					 | 
				
			||||||
      'Content-Type': 'application/json'
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    body: JSON.stringify({
 | 
					 | 
				
			||||||
      client_id: clientId,
 | 
					 | 
				
			||||||
      client_secret: clientSecret,
 | 
					 | 
				
			||||||
      redirect_uri: REDIRECT_URI,
 | 
					 | 
				
			||||||
      grant_type: 'authorization_code',
 | 
					 | 
				
			||||||
      code: code
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function getHomeTimeline(instanceName, accessToken) {
 | 
					 | 
				
			||||||
  let url = `https://${instanceName}/api/v1/timelines/home`
 | 
					 | 
				
			||||||
  return fetch(url, {
 | 
					 | 
				
			||||||
    method: 'GET',
 | 
					 | 
				
			||||||
    headers: {
 | 
					 | 
				
			||||||
      'Accept': 'application/json',
 | 
					 | 
				
			||||||
      'Authorization': `Bearer ${accessToken}`
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										43
									
								
								routes/_utils/mastodon/oauth.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								routes/_utils/mastodon/oauth.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,43 @@
 | 
				
			||||||
 | 
					const WEBSITE = 'https://pinafore.social'
 | 
				
			||||||
 | 
					const REDIRECT_URI = (typeof location !== 'undefined' ? location.origin : 'https://pinafore.social') + '/settings/instances'
 | 
				
			||||||
 | 
					const SCOPES = 'read write follow'
 | 
				
			||||||
 | 
					const CLIENT_NAME = 'Pinafore'
 | 
				
			||||||
 | 
					import { post, get, paramsString } from '../ajax'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function registerApplication(instanceName) {
 | 
				
			||||||
 | 
					  const url = `https://${instanceName}/api/v1/apps`
 | 
				
			||||||
 | 
					  return post(url, {
 | 
				
			||||||
 | 
					      client_name: CLIENT_NAME,
 | 
				
			||||||
 | 
					      redirect_uris: REDIRECT_URI,
 | 
				
			||||||
 | 
					      scopes: SCOPES,
 | 
				
			||||||
 | 
					      website: WEBSITE
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function generateAuthLink(instanceName, clientId) {
 | 
				
			||||||
 | 
					  let params = paramsString({
 | 
				
			||||||
 | 
					    'client_id': clientId,
 | 
				
			||||||
 | 
					    'redirect_uri': REDIRECT_URI,
 | 
				
			||||||
 | 
					    'response_type': 'code',
 | 
				
			||||||
 | 
					    'scope': SCOPES
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  return `https://${instanceName}/oauth/authorize?${params}`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function getAccessTokenFromAuthCode(instanceName, clientId, clientSecret, code) {
 | 
				
			||||||
 | 
					  let url = `https://${instanceName}/oauth/token`
 | 
				
			||||||
 | 
					  return post(url, {
 | 
				
			||||||
 | 
					    client_id: clientId,
 | 
				
			||||||
 | 
					    client_secret: clientSecret,
 | 
				
			||||||
 | 
					    redirect_uri: REDIRECT_URI,
 | 
				
			||||||
 | 
					    grant_type: 'authorization_code',
 | 
				
			||||||
 | 
					    code: code
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function getHomeTimeline(instanceName, accessToken) {
 | 
				
			||||||
 | 
					  let url = `https://${instanceName}/api/v1/timelines/home`
 | 
				
			||||||
 | 
					  return get(url, {
 | 
				
			||||||
 | 
					    'Authorization': `Bearer ${accessToken}`
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								routes/_utils/mastodon/user.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								routes/_utils/mastodon/user.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,8 @@
 | 
				
			||||||
 | 
					import { get } from '../ajax'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function getCurrentUser(instanceName, accessToken) {
 | 
				
			||||||
 | 
					  let url = `https://${instanceName}/api/v1/accounts/verify_credentials`
 | 
				
			||||||
 | 
					  return get(url, {
 | 
				
			||||||
 | 
					    'Authorization': `Bearer ${accessToken}`
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -65,6 +65,15 @@ store.compute(
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					store.compute(
 | 
				
			||||||
 | 
					  'currentInstanceData',
 | 
				
			||||||
 | 
					  ['currentInstance', 'loggedInInstances'],
 | 
				
			||||||
 | 
					  (currentInstance, loggedInInstances) => {
 | 
				
			||||||
 | 
					    return Object.assign({
 | 
				
			||||||
 | 
					      name: currentInstance
 | 
				
			||||||
 | 
					    }, loggedInInstances[currentInstance])
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (process.browser && process.env.NODE_ENV !== 'production') {
 | 
					if (process.browser && process.env.NODE_ENV !== 'production') {
 | 
				
			||||||
  window.store = store // for debugging
 | 
					  window.store = store // for debugging
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,9 @@
 | 
				
			||||||
  :global(.settings .free-text h1) {
 | 
					  :global(.settings .free-text h1) {
 | 
				
			||||||
    margin-bottom: 30px;
 | 
					    margin-bottom: 30px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  :global(.settings .free-text h2) {
 | 
				
			||||||
 | 
					    margin: 20px 0 10px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
  import SettingsNav from './SettingsNav.html';
 | 
					  import SettingsNav from './SettingsNav.html';
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,18 +5,78 @@
 | 
				
			||||||
<Layout page='settings'>
 | 
					<Layout page='settings'>
 | 
				
			||||||
  <SettingsLayout page='settings/instances/{{params.instanceName}}' label="{{params.instanceName}}">
 | 
					  <SettingsLayout page='settings/instances/{{params.instanceName}}' label="{{params.instanceName}}">
 | 
				
			||||||
    <h1>{{params.instanceName}}</h1>
 | 
					    <h1>{{params.instanceName}}</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {{#if currentUser}}
 | 
				
			||||||
 | 
					    <h2>Logged in as:</h2>
 | 
				
			||||||
 | 
					    <div class="current-user">
 | 
				
			||||||
 | 
					      <img src="{{currentUser.avatar}}" />
 | 
				
			||||||
 | 
					      <a rel="noopener" target="_blank" href="{{currentUser.url}}">@{{currentUser.acct}}</a>
 | 
				
			||||||
 | 
					      <span class="acct-name">{{currentUser.display_name}}</span>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <h2>Theme:</h2>
 | 
				
			||||||
 | 
					    <form class="theme-chooser">
 | 
				
			||||||
 | 
					      <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>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </form>
 | 
				
			||||||
 | 
					    {{/if}}
 | 
				
			||||||
  </SettingsLayout>
 | 
					  </SettingsLayout>
 | 
				
			||||||
</Layout>
 | 
					</Layout>
 | 
				
			||||||
 | 
					<style>
 | 
				
			||||||
 | 
					  .current-user {
 | 
				
			||||||
 | 
					    padding: 20px;
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    align-items: center;
 | 
				
			||||||
 | 
					    font-size: 1.3em;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .current-user img {
 | 
				
			||||||
 | 
					    width: 64px;
 | 
				
			||||||
 | 
					    height: 64px;
 | 
				
			||||||
 | 
					    border-radius: 4px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .current-user img, .current-user a, .current-user span {
 | 
				
			||||||
 | 
					    margin-right: 20px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .theme-chooser {
 | 
				
			||||||
 | 
					    display: block;
 | 
				
			||||||
 | 
					    padding: 20px;
 | 
				
			||||||
 | 
					    line-height: 2em;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .theme-group {
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    align-items: center;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .theme-chooser label {
 | 
				
			||||||
 | 
					    margin: 2px 10px 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
  import { store } from '../../_utils/store'
 | 
					  import { store } from '../../_utils/store'
 | 
				
			||||||
  import Layout from '../../_components/Layout.html'
 | 
					  import Layout from '../../_components/Layout.html'
 | 
				
			||||||
  import SettingsLayout from '../_components/SettingsLayout.html'
 | 
					  import SettingsLayout from '../_components/SettingsLayout.html'
 | 
				
			||||||
 | 
					  import { getCurrentUser } from '../../_utils/mastodon/user'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export default {
 | 
					  export default {
 | 
				
			||||||
    components: {
 | 
					    components: {
 | 
				
			||||||
      Layout,
 | 
					      Layout,
 | 
				
			||||||
      SettingsLayout
 | 
					      SettingsLayout
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    store: () => store
 | 
					    store: () => store,
 | 
				
			||||||
 | 
					    oncreate: async function () {
 | 
				
			||||||
 | 
					      let currentInstanceData = this.store.get('currentInstanceData')
 | 
				
			||||||
 | 
					      let currentUser = await getCurrentUser(currentInstanceData.name, currentInstanceData.access_token)
 | 
				
			||||||
 | 
					      this.set({currentUser: currentUser})
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,7 @@
 | 
				
			||||||
    </form>
 | 
					    </form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {{#if !$isUserLoggedIn}}
 | 
					    {{#if !$isUserLoggedIn}}
 | 
				
			||||||
    <p>Don't have an instance? <a href="https://joinmastodon.org">Join Mastodon!</a></p>
 | 
					    <p>Don't have an instance? <a rel="noopener" target="_blank" href="https://joinmastodon.org">Join Mastodon!</a></p>
 | 
				
			||||||
    {{/if}}
 | 
					    {{/if}}
 | 
				
			||||||
  </SettingsLayout>
 | 
					  </SettingsLayout>
 | 
				
			||||||
</Layout>
 | 
					</Layout>
 | 
				
			||||||
| 
						 | 
					@ -49,8 +49,7 @@
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
  import Layout from '../../_components/Layout.html';
 | 
					  import Layout from '../../_components/Layout.html';
 | 
				
			||||||
  import SettingsLayout from '../_components/SettingsLayout.html'
 | 
					  import SettingsLayout from '../_components/SettingsLayout.html'
 | 
				
			||||||
  import { registerApplication, generateAuthLink, getAccessTokenFromAuthCode } from '../../_utils/mastodon'
 | 
					  import { registerApplication, generateAuthLink, getAccessTokenFromAuthCode } from '../../_utils/mastodon/oauth'
 | 
				
			||||||
  import { databasePromise } from '../../_utils/database'
 | 
					 | 
				
			||||||
  import { store } from '../../_utils/store'
 | 
					  import { store } from '../../_utils/store'
 | 
				
			||||||
  import { goto } from 'sapper/runtime.js'
 | 
					  import { goto } from 'sapper/runtime.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -74,12 +73,12 @@
 | 
				
			||||||
      onReceivedOauthCode: async function(code) {
 | 
					      onReceivedOauthCode: async function(code) {
 | 
				
			||||||
        let currentRegisteredInstanceName = this.store.get('currentRegisteredInstanceName')
 | 
					        let currentRegisteredInstanceName = this.store.get('currentRegisteredInstanceName')
 | 
				
			||||||
        let currentRegisteredInstance = this.store.get('currentRegisteredInstance')
 | 
					        let currentRegisteredInstance = this.store.get('currentRegisteredInstance')
 | 
				
			||||||
        let instanceData = await (await getAccessTokenFromAuthCode(
 | 
					        let instanceData = await getAccessTokenFromAuthCode(
 | 
				
			||||||
          currentRegisteredInstanceName,
 | 
					          currentRegisteredInstanceName,
 | 
				
			||||||
          currentRegisteredInstance.client_id,
 | 
					          currentRegisteredInstance.client_id,
 | 
				
			||||||
          currentRegisteredInstance.client_secret,
 | 
					          currentRegisteredInstance.client_secret,
 | 
				
			||||||
          code
 | 
					          code
 | 
				
			||||||
        )).json()
 | 
					        )
 | 
				
			||||||
        // TODO: handle error
 | 
					        // TODO: handle error
 | 
				
			||||||
        let loggedInInstances = this.store.get('loggedInInstances')
 | 
					        let loggedInInstances = this.store.get('loggedInInstances')
 | 
				
			||||||
        let loggedInInstancesInOrder = this.store.get('loggedInInstancesInOrder')
 | 
					        let loggedInInstancesInOrder = this.store.get('loggedInInstancesInOrder')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue