Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,28 @@ import { useTitle } from '@vueuse/core'
import { storeToRefs } from 'pinia'
import { computed } from 'vue'
import { THEME_MODES, useSettingsStore } from '@/shared/stores'
import { BadgeNumber, IconSvg } from '@/shared/ui'
import { BadgeNumber, IconSvg, SelectControl } from '@/shared/ui'

const settingsStore = useSettingsStore()
const { changeTheme, changeNavbar, changeEventCountsVisibility, changeActiveCodeEditor } =
settingsStore
const { themeType, isFixedHeader, isVisibleEventCounts, codeEditor } = storeToRefs(settingsStore)
const {
changeTheme,
changeNavbar,
changeEventCountsVisibility,
setAutoDeleteEventsTime,
changeActiveCodeEditor
} = settingsStore
const { themeType, isFixedHeader, isVisibleEventCounts, autoDeleteEventsTime, codeEditor } =
storeToRefs(settingsStore)

const isDarkMode = computed(() => themeType.value === THEME_MODES.DARK)

const deleteEventsAfter = computed<string>({
get: () => (autoDeleteEventsTime.value === 'none' ? 'none' : String(autoDeleteEventsTime.value)),
set: (val) => {
setAutoDeleteEventsTime(val)
}
})

// TODO: add throttle
const changeCodeEditor = (event: Event) => {
const editor = (event.target as HTMLInputElement).value
Expand Down Expand Up @@ -114,6 +127,21 @@ useTitle('Settings | Buggregator')
</div>
</div>

<div class="settings-page-content__title">
Delete Events After:
</div>

<SelectControl
v-model="deleteEventsAfter"
name="delete_events_after"
:options="[
{ value: 'none', text: 'No' },
{ value: '1', text: '1 min' },
{ value: '5', text: '5 min' },
{ value: '10', text: '10 min' }
]"
/>

<div class="settings-page-content__title">
Code Editor Open Link:
</div>
Expand Down
116 changes: 116 additions & 0 deletions src/shared/lib/use-events/auto-delete-events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { storeToRefs } from "pinia";
import { watch } from "vue";
import { useEventsStore, useSettingsStore } from "../../stores";
import type { EventId } from "../../types";
import { useEventsApi } from "./use-events-api";

type AutoDeleteTime = number | "none";

const autoDeleteTimers = new Map<EventId, ReturnType<typeof setTimeout>>();
let autoDeleteInitialized = false;

const toAutoDeleteMs = (val: AutoDeleteTime): number | null => {
if (val === "none") return null;
return val * 60 * 1000;
};

const clearAutoDeleteTimer = (eventId: EventId) => {
const timer = autoDeleteTimers.get(eventId);
if (!timer) return;
globalThis.clearTimeout(timer);
autoDeleteTimers.delete(eventId);
};

const clearAllAutoDeleteTimers = () => {
autoDeleteTimers.forEach((timer) => globalThis.clearTimeout(timer));
autoDeleteTimers.clear();
};

export const ensureAutoDeleteWatcher = () => {
if (autoDeleteInitialized) return;
autoDeleteInitialized = true;

const eventsStore = useEventsStore();
const settingsStore = useSettingsStore();
const eventsApi = useEventsApi();

const { events, lockedIds } = storeToRefs(eventsStore);
const { autoDeleteEventsTime } = storeToRefs(settingsStore);

const schedule = (eventId: EventId) => {
const ms = toAutoDeleteMs(autoDeleteEventsTime.value);
if (ms === null || autoDeleteTimers.has(eventId)) return;

const timer = globalThis.setTimeout(() => {
autoDeleteTimers.delete(eventId);

const locked = lockedIds.value ?? [];
if (locked.includes(eventId)) return;

void eventsApi.removeById(eventId);
}, ms);

autoDeleteTimers.set(eventId, timer);
};

const rescheduleAll = () => {
clearAllAutoDeleteTimers();

const ms = toAutoDeleteMs(autoDeleteEventsTime.value);
if (ms === null) return;

events.value.forEach(({ uuid }) => {
schedule(uuid);
});
};

const syncTimers = (currentIds: Set<EventId>, prevIds: Set<EventId>) => {
prevIds.forEach((id) => {
if (!currentIds.has(id)) {
clearAutoDeleteTimer(id);
}
});

if (toAutoDeleteMs(autoDeleteEventsTime.value) === null) return;

currentIds.forEach((id) => {
if (!prevIds.has(id)) {
schedule(id);
}
});
};

watch(
autoDeleteEventsTime,
() => {
rescheduleAll();
},
{ immediate: true },
);

watch(
() => events.value.map(({ uuid }) => uuid),
(current, prev) => {
const currentIds = new Set(current);
const prevIds = new Set(prev ?? []);

syncTimers(currentIds, prevIds);
},
);

watch(
() => lockedIds.value.slice(),
(current, prev) => {
const currentIds = new Set(current);
const prevIds = new Set(prev ?? []);

const eventsIds = new Set(events.value.map(({ uuid }) => uuid));
const unlockedIds = new Set(
[...prevIds].filter((id) => !currentIds.has(id) && eventsIds.has(id)),
);

syncTimers(currentIds, prevIds);
syncTimers(unlockedIds, new Set<EventId>());
},
);
};
1 change: 0 additions & 1 deletion src/shared/lib/use-events/use-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { useApiTransport } from "../use-api-transport";
import { normalizeUnknownEvent } from "./normalize-unknown-event";
import { type TUseEventsApi, useEventsApi } from "./use-events-api";


type TUseEvents = () => {
normalizeUnknownEvent: (event: ServerEvent<unknown>) => NormalizedEvent<unknown>
events: TUseEventsApi
Expand Down
2 changes: 2 additions & 0 deletions src/shared/stores/events/events-store.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { defineStore } from "pinia";
import { PAGE_TYPES} from "../../constants";
import { ensureAutoDeleteWatcher } from "../../lib/use-events/auto-delete-events";
import {useSettings} from "../../lib/use-settings";
import {
type EventId,
Expand Down Expand Up @@ -79,6 +80,7 @@ export const useEventsStore = defineStore("eventsStore", {
async initialize (): Promise<void> {
const {api: { getProjects }} = useSettings();
this.initActiveProjectKey();
ensureAutoDeleteWatcher();

try {
const { data } = await getProjects();
Expand Down
24 changes: 24 additions & 0 deletions src/shared/stores/settings/local-storage-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,30 @@ export const setStoredEventsCountVisibility = (state: boolean) => {
window?.localStorage?.setItem(LocalStorageKeys.EventCounts, String(state));
}

export const getStoredAutoDeleteEventsTime = (): number | 'none' => {
const raw = window?.localStorage?.getItem(
LocalStorageKeys.AutoDeleteEventsTime,
);
if (raw === null) {
return 'none';
}
const value = Number(raw);
return Number.isFinite(value) && value > 0 ? value : 'none';
};

export const setStoredAutoDeleteEventsTime = (minutes: number | 'none'): void => {
if (minutes === 'none') {
window?.localStorage?.removeItem(
LocalStorageKeys.AutoDeleteEventsTime,
);
return;
}

window?.localStorage?.setItem(
LocalStorageKeys.AutoDeleteEventsTime,
String(minutes),
);
};

export const getStoredPrimaryCodeEditor = (): string => {
const storedCodeEditor = window?.localStorage?.getItem(LocalStorageKeys.CodeEditor);
Expand Down
16 changes: 16 additions & 0 deletions src/shared/stores/settings/settings-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
getStoredFixedHeader,
getStoredActiveTheme,
setStoredEventsCountVisibility,
getStoredAutoDeleteEventsTime,
setStoredAutoDeleteEventsTime,
setStoredFixedHeader,
setStoredActiveTheme,
getStoredPrimaryCodeEditor,
Expand All @@ -23,6 +25,7 @@ export const useSettingsStore = defineStore("settingsStore", {
themeType: getStoredActiveTheme(),
isFixedHeader: getStoredFixedHeader(),
isVisibleEventCounts: getStoredEventsCountVisibility(),
autoDeleteEventsTime: getStoredAutoDeleteEventsTime(),
availableEvents: [] as EventType[],
}),
getters: {
Expand Down Expand Up @@ -72,6 +75,19 @@ export const useSettingsStore = defineStore("settingsStore", {

setStoredEventsCountVisibility(this.isVisibleEventCounts)
},
setAutoDeleteEventsTime(value: string | number | 'none') {
const normalized =
value === 'none'
? 'none'
: Number(value);

this.autoDeleteEventsTime =
normalized === 'none' || !Number.isFinite(normalized) || normalized <= 0
? 'none'
: normalized;

setStoredAutoDeleteEventsTime(this.autoDeleteEventsTime);
},
changeActiveCodeEditor(editor: string) {
this.codeEditor = editor;

Expand Down
1 change: 1 addition & 0 deletions src/shared/types/local-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export enum LocalStorageKeys {
Theme = "theme",
Navbar = "navbar",
EventCounts = "event_counts",
AutoDeleteEventsTime = "autodelete_events_time_in_minutes",
CodeEditor = "code_editor",
Token = "token",
}
Expand Down
Loading
Loading