Skip to content

Commit

Permalink
feat: Add Filter by Tags option (#50)
Browse files Browse the repository at this point in the history
* Improve sorting performance and code readability

* Add Filter by Tags option
  • Loading branch information
navorite committed Nov 7, 2023
1 parent 7bc9dae commit 1eef72d
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 61 deletions.
22 changes: 4 additions & 18 deletions src/lib/components/popup/Header.svelte
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
<script lang="ts">
import { EXT_MODE, EXT_NAME, isPopup } from '@/lib/constants';
import {
settings,
filterOptions,
notification,
filtered
} from '@/lib/stores';
import { settings, filterOptions, notification } from '@/lib/stores';
import {
SearchBar,
Notification,
IconButton,
Modal,
Donate,
Sorting
Sorting,
TagFilter
} from '@/lib/components';
import { openFullView, openOptions } from '@utils/extension';
Expand All @@ -30,19 +26,9 @@
{/if}
</h1>

<TagFilter />
<Sorting />

{#await $filtered then filtered}
{#if filtered?.length}
<div
aria-label="Number of sessions"
class="card bg-info text-white hover:bg-info-focus"
>
{filtered.length} Session{filtered.length > 1 ? 's' : ''}
</div>
{/if}
{/await}

<Notification detail={$notification} />

<div class="ml-auto flex h-full w-max items-center justify-end gap-2">
Expand Down
5 changes: 2 additions & 3 deletions src/lib/components/popup/sessions/Sorting.svelte
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
<script lang="ts">
import { sessions, settings } from '@/lib/stores';
import type { SortMethod } from '@/lib/types';
import { settings } from '@/lib/stores';
function changeSortMethod(val: string) {
settings.changeSetting('sortMethod', val as SortMethod);
sessions.sort();
}
</script>

<select
name="sort-method"
id="sort-method"
class="rounded-md bg-neutral-3 px-2 py-1 text-xs"
class="min-w-[5rem] rounded-md bg-neutral-3 p-1 text-center text-xs"
value={$settings.sortMethod}
on:change={(ev) => changeSortMethod(ev.currentTarget.value)}
>
Expand Down
29 changes: 29 additions & 0 deletions src/lib/components/popup/sessions/TagFilter.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script lang="ts">
import {
filterOptions,
finished,
sessions,
settings,
tags
} from '@/lib/stores';
$: tagsFilter = $settings.tagsFilter;
$: if (tagsFilter !== '__all__' && finished && !$tags[tagsFilter])
settings.changeSetting('tagsFilter', '__all__');
</script>

<select
name="tagsFilter"
id="tagsFilter"
class="min-w-[11rem] rounded-md bg-neutral-3 p-1 text-center text-xs"
bind:value={$filterOptions.tagsFilter}
on:change={(ev) => {
settings.changeSetting('tagsFilter', ev.currentTarget.value);
}}
>
<option value="__all__">All ({$sessions?.length ?? 0})</option>
{#each Object.keys($tags) as tag}
<option value={tag}>{tag} ({$tags[tag]})</option>
{/each}
</select>
1 change: 1 addition & 0 deletions src/lib/components/popup/sessions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export { default as Session } from './Session.svelte';
export { default as Sessions } from './Sessions.svelte';
export { default as CurrentSession } from './CurrentSession.svelte';
export { default as Sorting } from './Sorting.svelte';
export { default as TagFilter } from './TagFilter.svelte';
84 changes: 48 additions & 36 deletions src/lib/stores/sessions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,35 @@ import { derived, get, writable, type Writable } from 'svelte/store';
import { sessionsDB } from '@utils/database';
import { settings, notification, filterOptions } from '@/lib/stores';
import { MESSAGES } from '@constants/notifications';
import { log, generateSession, sendMessage, sortSessions } from '@/lib/utils';
import {
log,
generateSession,
sendMessage,
filterTagsAndSort
} from '@/lib/utils';
import browser from 'webextension-polyfill';

export let finished = false;

export const sessions = (() => {
const { subscribe, set, update }: Writable<ESession[]> = writable([]);

const selection: Writable<ESession> = writable();

load();

async function load() {
await settings.init(); // to fix inconsistent behaviour with FF and Chrome - need to check
const count = await sessionsDB.streamSessions('dateSaved', set, 50);

const { selectionId, sortMethod } = get(settings);
log.info(`[sessions.load] loaded ${count} session`);

const count = await sessionsDB.streamSessions(
'dateSaved',
(sessions) => set(sortSessions(sortMethod, sessions)),
50
);
await settings.init(); // to fix inconsistent behaviour with FF and Chrome - need to check

log.info(`[sessions.load] loaded ${count} session`);
const { selectionId } = get(settings);

selectById(selectionId);

finished = true;
}

async function add(session: ESession) {
Expand All @@ -43,12 +49,8 @@ export const sessions = (() => {
update((sessions) => {
generated.windows = { length: generated.windows.length } as EWindow[]; //unref the obj for GC

const { sortMethod } = get(settings);

sessions.push(generated);

sortSessions(sortMethod, sessions);

notify(sessions, generated.id);

return sessions;
Expand Down Expand Up @@ -78,8 +80,6 @@ export const sessions = (() => {

sessions[sessions.indexOf(target)] = target;

sortSessions(get(settings).sortMethod, sessions);

notify(sessions, target.id);

return sessions;
Expand Down Expand Up @@ -123,7 +123,7 @@ export const sessions = (() => {
filtered.push(session);
}
}
resolve(sortSessions(get(settings).sortMethod, filtered)); //subject to change;
resolve(filtered); //subject to change;
}, 250);
});

Expand Down Expand Up @@ -238,34 +238,46 @@ export const sessions = (() => {
select,
selectById,
set: selection.set
}, //TODO: remove the ability to set
sort() {
update((sessions) => {
return sortSessions(get(settings).sortMethod, sessions);
});
}
} //TODO: remove the ability to set
};
})();

let query = '';
export const filtered = (() => {
let currentQuery = '';
let filteredList: ESession[] = [];

export const filtered = derived(
[sessions, filterOptions],
(
[$sessions, $filterOptions],
set: (val: ESession[] | Promise<ESession[]>) => void,
update
) => {
if (!$filterOptions.query) return set($sessions);
const { subscribe } = derived(
[sessions, filterOptions],
([$sessions, $filterOptions], set: (val: ESession[]) => void) => {
const { query, tagsFilter, sortMethod } = $filterOptions;

if (query !== $filterOptions.query) {
query = $filterOptions.query;
if (!query) {
set(filterTagsAndSort($sessions, sortMethod, tagsFilter));
} else if (currentQuery !== query) {
currentQuery = query;

return set(sessions.filter($filterOptions.query.trim().toLowerCase()));
sessions.filter(query.trim().toLowerCase()).then((val) => {
filteredList = val;

set(filterTagsAndSort(filteredList, sortMethod, tagsFilter));
});
} else set(filterTagsAndSort(filteredList, sortMethod, tagsFilter));
}
);

return { subscribe };
})();

export const tags = derived(sessions, ($sessions) => {
const tagsList: Record<string, number> = {};

update(async (val) => sortSessions(get(settings).sortMethod, await val));
for (const session of $sessions) {
if (session.tags) {
tagsList[session.tags] = (tagsList[session.tags] ?? 0) + 1;
}
}
);

return tagsList;
});

export const currentSession: Writable<ESession> = writable();
24 changes: 21 additions & 3 deletions src/lib/stores/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import {
} from '@/lib/utils';
import { autoSaveDefaults } from '@/lib/constants';

export const filterOptions: Writable<FilterOptions> = writable({ query: '' });
export const filterOptions: Writable<FilterOptions> = writable({
query: '',
sortMethod: 'newest',
tagsFilter: '__all__'
});

export const settings = (() => {
let loaded: Promise<ESettings>;
Expand All @@ -28,7 +32,8 @@ export const settings = (() => {
tags: {},
doNotAskForTitle: true,
excludePinned: true,
sortMethod: 'newest'
sortMethod: 'newest',
tagsFilter: '__all__'
};

const { subscribe, set, update } = writable(defaultSettings);
Expand All @@ -53,6 +58,12 @@ export const settings = (() => {

applyTheme(settings.darkMode, false);

filterOptions.set({
sortMethod: settings.sortMethod,
tagsFilter: settings.tagsFilter,
query: ''
});

loaded = Promise.resolve({} as ESettings);

const updated = await getStorageItem('updated' as keyof ESettings, false);
Expand All @@ -79,7 +90,14 @@ export const settings = (() => {
if (change === 'selectionId')
sessions.selection.selectById(settings[change]);

if (change === 'sortMethod') sessions.sort();
if (change === 'sortMethod' || change === 'tagsFilter')
filterOptions.update((val) => {
(val[
change as keyof FilterOptions
] as FilterOptions[keyof FilterOptions]) = settings[change];

return val;
});
}
return settings;
});
Expand Down
3 changes: 3 additions & 0 deletions src/lib/types/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export interface ESession {

export interface FilterOptions {
query: string;
sortMethod: SortMethod;
tagsFilter: '__all__' | (string & NonNullable<unknown>);
default_tabs?: boolean;
}

Expand Down Expand Up @@ -73,4 +75,5 @@ export interface ESettings {
doNotAskForTitle: boolean;
excludePinned: boolean;
sortMethod: SortMethod;
tagsFilter: '__all__' | (string & NonNullable<unknown>);
}
2 changes: 1 addition & 1 deletion src/lib/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ export * from './backup';
export * from './handleFilterListChange';
export * from './getRelativeTime';
export * from './input';
export * from './sortSessions';
export * from './sessionsFilters';
14 changes: 14 additions & 0 deletions src/lib/utils/sortSessions.ts → src/lib/utils/sessionsFilters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,17 @@ export function sortSessions(sortMethod: SortMethod, sessions: ESession[]) {
}
}
}

export function filterTags(sessions: ESession[], tag: '__all__' | string) {
if (tag === '__all__') return sessions;

return sessions.filter((session) => session.tags === tag);
}

export function filterTagsAndSort(
sessions: ESession[],
sortMethod: SortMethod,
tagsFilter: string
) {
return sortSessions(sortMethod, filterTags(sessions, tagsFilter));
}

0 comments on commit 1eef72d

Please sign in to comment.