Emoji favicons for the web
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add migration from 1.00

+148 -54
+22 -8
source/background.ts
··· 3 3 */ 4 4 5 5 import type { Tab, TabChangeInfo } from 'browser'; 6 - import type { Settings } from './types.ts'; 6 + import type { Settings, SettingsV1 } from './settings.ts'; 7 7 8 + import browserAPI from 'browser'; 9 + import { 10 + DEFAULT_SETTINGS, 11 + isV1Settings, 12 + LEGACY_STORAGE_KEYS, 13 + migrateFromV1, 14 + STORAGE_KEYS, 15 + } from './settings.ts'; 8 16 import FaviconData from './utilities/favicon_data.ts'; 9 - import { defaultSettings, STORAGE_KEYS } from './types.ts'; 10 17 import Autoselector from './utilities/autoselector.ts'; 11 - import browserAPI from 'browser'; 12 18 13 19 const autoselector = new Autoselector(); 14 - let settings: Settings = defaultSettings; 20 + let settings: Settings = DEFAULT_SETTINGS; 15 21 16 22 syncSettings(); 17 23 browserAPI.storage.onChanged.addListener(syncSettings); ··· 33 39 ); 34 40 35 41 async function syncSettings() { 36 - const storedSettings: Settings = await browserAPI.storage.sync.get( 37 - STORAGE_KEYS, 38 - ) as Settings; 39 - if (storedSettings) settings = storedSettings; 42 + const storedSettings: Settings | SettingsV1 = await browserAPI.storage.sync 43 + .get(STORAGE_KEYS) as Settings | SettingsV1; 44 + 45 + if (!storedSettings) return; 46 + 47 + if (isV1Settings(storedSettings)) { 48 + settings = migrateFromV1(storedSettings); 49 + await browserAPI.storage.sync.remove(LEGACY_STORAGE_KEYS); 50 + await browserAPI.storage.sync.set(settings); 51 + } else { 52 + settings = storedSettings; 53 + } 40 54 } 41 55 42 56 function listItemMatchesUrl(favicon: FaviconData, url: string) {
+2 -2
source/content_script.ts
··· 7 7 */ 8 8 import browserAPI from 'browser'; 9 9 10 - import type { Favicon } from './types.ts'; 10 + import type FaviconData from './utilities/favicon_data.ts'; 11 11 import { appendFaviconLink } from './utilities/favicon_helpers.ts'; 12 12 13 13 browserAPI.storage.onChanged.addListener((changes) => { ··· 34 34 favicon, 35 35 shouldOverride, 36 36 }: { 37 - favicon: Favicon; 37 + favicon: FaviconData; 38 38 shouldOverride: boolean; 39 39 }) => { 40 40 if (favicon.emoji) {
+1 -1
source/options.tsx
··· 3 3 import { Fragment, h, render } from 'preact'; 4 4 import { useCallback } from 'preact/hooks'; 5 5 6 - import { Settings, STORAGE_KEYS } from './types.ts'; 6 + import { Settings, STORAGE_KEYS } from './settings.ts'; 7 7 import Header from './components/header.tsx'; 8 8 import Switch from './components/switch.tsx'; 9 9
+2 -2
source/pages/favicons_page.tsx
··· 4 4 import { Fragment, h } from 'preact'; 5 5 import { useEffect } from 'preact/hooks'; 6 6 7 - import { defaultSettings, Settings } from '../types.ts'; 7 + import { DEFAULT_SETTINGS, Settings } from '../settings.ts'; 8 8 import List from '../components/list.tsx'; 9 9 import Only from '../components/only.tsx'; 10 10 import useListState from '../hooks/use_list_state.ts'; ··· 22 22 siteList = [], 23 23 ignoreList = [], 24 24 features = {}, 25 - } = storage?.cache || defaultSettings; 25 + } = storage?.cache || DEFAULT_SETTINGS; 26 26 const { enableSiteIgnore } = features; 27 27 const siteListState = useListState(siteList); 28 28 const ignoreListState = useListState(ignoreList);
+2 -2
source/pages/settings_page.tsx
··· 4 4 import { Fragment, h } from 'preact'; 5 5 import { useCallback } from 'preact/hooks'; 6 6 7 - import { defaultSettings, Settings } from '../types.ts'; 7 + import { DEFAULT_SETTINGS, Settings } from '../settings.ts'; 8 8 import Checkbox, { Target } from '../components/checkbox.tsx'; 9 9 import Only from '../components/only.tsx'; 10 10 import { t } from '../utilities/i18n.ts'; ··· 17 17 } 18 18 19 19 const SettingsPage = ({ save, storage }: SettingsProps) => { 20 - const { cache = defaultSettings, setCache } = storage || {}; 20 + const { cache = DEFAULT_SETTINGS, setCache } = storage || {}; 21 21 const { enableFaviconAutofill, enableSiteIgnore, enableOverrideAll } = 22 22 cache.features || {}; 23 23
+1 -1
source/popup.tsx
··· 7 7 import FaviconData from './utilities/favicon_data.ts'; 8 8 import useBrowserStorage from './hooks/use_browser_storage.ts'; 9 9 import useStatus from './hooks/use_status.ts'; 10 - import { Settings, STORAGE_KEYS } from './types.ts'; 10 + import { Settings, STORAGE_KEYS } from './settings.ts'; 11 11 12 12 const queryOptions = { active: true }; 13 13
+118
source/settings.ts
··· 1 + import FaviconData from './utilities/favicon_data.ts'; 2 + import manifest from './manifest.json' assert { type: 'json' }; 3 + import * as emoji from 'emoji'; 4 + 5 + export interface Settings { 6 + version: string; 7 + siteList: FaviconData[]; 8 + ignoreList: FaviconData[]; 9 + 10 + features: { 11 + enableFaviconAutofill?: boolean; 12 + enableSiteIgnore?: boolean; 13 + enableOverrideAll?: boolean; 14 + }; 15 + } 16 + 17 + /* Legacy Interfaces */ 18 + export interface SettingsV1 { 19 + flagReplaced: boolean; 20 + overrideAll: boolean; 21 + overrides: EmojiV1[]; 22 + skips: string[]; 23 + } 24 + 25 + export interface EmojiV1 { 26 + emoji: string | EmojiMartEmojiV1; 27 + filter: string; 28 + } 29 + 30 + export type EmojiMartEmojiV1 = { 31 + colons: string; 32 + emoticons: string[]; 33 + id: string; 34 + name: string; 35 + native: string; 36 + skin: null; 37 + unified: string; 38 + }; 39 + 40 + export const DEFAULT_SETTINGS: Settings = { 41 + version: manifest.version, 42 + siteList: [], 43 + ignoreList: [], 44 + 45 + features: { 46 + enableFaviconAutofill: false, 47 + enableSiteIgnore: false, 48 + enableOverrideAll: false, 49 + }, 50 + }; 51 + 52 + export const LEGACY_STORAGE_KEYS = [ 53 + 'flagReplaced', 54 + 'overrideAll', 55 + 'overrides', 56 + 'skips', 57 + ]; 58 + export const STORAGE_KEYS = Object.freeze( 59 + Object.keys(DEFAULT_SETTINGS) 60 + // Legacy settings for migration purposes 61 + .concat(LEGACY_STORAGE_KEYS), 62 + ); 63 + 64 + export function parseVersion(version: string): { 65 + major: number; 66 + minor: number; 67 + patch: number; 68 + } { 69 + if (!version) throw new Error('No Version Detected'); 70 + 71 + const [major, minor, patch] = version.split('.'); 72 + 73 + if (major == null || minor == null || patch == null) { 74 + throw new Error(`error parsing version ${version} `); 75 + } 76 + 77 + return { 78 + major: Number(major), 79 + minor: Number(minor), 80 + patch: Number(patch), 81 + }; 82 + } 83 + 84 + export function isV1Settings( 85 + settings: Settings | SettingsV1, 86 + ): settings is SettingsV1 { 87 + if ( 88 + 'flagReplaced' in settings || 89 + 'overrideAll' in settings || 90 + 'overrides' in settings || 91 + 'skips' in settings 92 + ) { 93 + return true; 94 + } else return false; 95 + } 96 + 97 + export function migrateFromV1(legacySettings: SettingsV1): Settings { 98 + const settings = { ...DEFAULT_SETTINGS }; 99 + 100 + settings.features = { 101 + enableFaviconAutofill: true, 102 + enableOverrideAll: legacySettings.overrideAll, 103 + enableSiteIgnore: Boolean(legacySettings?.skips?.length), 104 + }; 105 + 106 + settings.siteList = (legacySettings?.overrides || []) 107 + .map((legacyFavicon): FaviconData => { 108 + const emojiInput = typeof legacyFavicon.emoji === 'string' 109 + ? emoji.infoByCode(legacyFavicon.emoji) 110 + : emoji.infoByCode(legacyFavicon.emoji.native); 111 + return new FaviconData(emojiInput, legacyFavicon.filter); 112 + }); 113 + 114 + settings.ignoreList = (legacySettings?.skips || []) 115 + .map((skip) => new FaviconData(undefined, skip)); 116 + 117 + return settings; 118 + }
-38
source/types.ts
··· 1 - import FaviconData from './utilities/favicon_data.ts'; 2 - 3 - export interface Settings { 4 - siteList: FaviconData[]; 5 - ignoreList: FaviconData[]; 6 - 7 - features: { 8 - enableFaviconAutofill?: boolean; 9 - enableSiteIgnore?: boolean; 10 - enableOverrideAll?: boolean; 11 - }; 12 - } 13 - 14 - /** 15 - * Video, Image, Emoji are all pointers to source 16 - * This is so we can point multiple ids to the same data 17 - */ 18 - export interface Source { 19 - id: string; // Generated by DB 20 - data: string; // emoji string or base64 image 21 - } 22 - 23 - export const defaultSettings: Settings = { 24 - siteList: [], 25 - ignoreList: [], 26 - 27 - features: { 28 - enableFaviconAutofill: false, 29 - enableSiteIgnore: false, 30 - enableOverrideAll: false, 31 - }, 32 - }; 33 - 34 - export const STORAGE_KEYS = Object.freeze([ 35 - 'siteList', 36 - 'ignoreList', 37 - 'features', 38 - ]);