Skip to content
This repository was archived by the owner on Dec 16, 2024. It is now read-only.

Commit 94c88ef

Browse files
authored
Feat/autosync modq (#1022)
* Fix deleting messages when emote is deleted * Autosync modQ
1 parent 9bdb1f5 commit 94c88ef

File tree

3 files changed

+75
-43
lines changed

3 files changed

+75
-43
lines changed

src/components/modal/ModalError.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ const emit = defineEmits<{
2424
}>();
2525
2626
defineProps<{
27-
error: string;
28-
detail: string;
29-
code: number;
27+
error?: string;
28+
detail?: string;
29+
code?: number;
3030
gql?: GraphQLErrors;
3131
}>();
3232
</script>

src/views/admin/ModQueue/AdminModQueue.vue

Lines changed: 63 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<main ref="mainEl" class="admin-mod-queue">
3-
<div class="mod-queue-category-item q-floating" :disabled="query.loading.value" @click="refetch">
3+
<div class="mod-queue-category-item q-floating" :disabled="query.loading.value" @click="query.refetch()">
44
{{ query.loading.value ? "Loading..." : "Refetch" }}
55
</div>
66
<div class="mod-queue-stats">
@@ -19,16 +19,6 @@
1919
:error="country !== '' && !CISO2.has(country.toUpperCase())"
2020
/>
2121
</div>
22-
23-
<div>
24-
<label for="limit">Limit: {{ _limit }}</label>
25-
<RangeInput v-model.number="_limit" :min="1" :max="250" width="8em" />
26-
</div>
27-
</section>
28-
<section class="mod-queue-categories">
29-
<div class="mod-queue-category-item" :disabled="query.loading.value" @click="refetch">
30-
{{ query.loading.value ? "Loading..." : "Refetch " }}
31-
</div>
3222
<div ref="groupDropdown" class="mod-queue-dropdown mod-queue-category-item">
3323
<div class="mod-queue-category-item" :active="dropdownOpen" @click="dropdownOpen = !dropdownOpen">
3424
<Icon icon="language" />
@@ -53,6 +43,16 @@
5343
</div>
5444
</div>
5545
</div>
46+
<div>
47+
<label for="limit">Limit: {{ _limit }}</label>
48+
<RangeInput v-model.number="_limit" :min="1" :max="250" width="8em" />
49+
</div>
50+
</section>
51+
<section class="mod-queue-categories">
52+
<div class="mod-queue-category-item" :disabled="query.loading.value" @click="query.refetch()">
53+
{{ query.loading.value ? "Loading..." : "Refetch " }}
54+
</div>
55+
<div class="mod-queue-category-item" :active="autoSync" @click="autoSync = !autoSync">AutoSync</div>
5656
</section>
5757
<section class="mod-queue-categories">
5858
<div class="mod-queue-category-item" :active="bigMode" @click="bigMode = !bigMode">Zoomed</div>
@@ -111,12 +111,13 @@
111111
<script setup lang="ts">
112112
import { computed, nextTick, ref, toRaw, watch } from "vue";
113113
import { useQuery } from "@vue/apollo-composable";
114-
import { debouncedRef, onClickOutside, useElementVisibility } from "@vueuse/core";
114+
import { debouncedRef, onClickOutside, useElementVisibility, useIntervalFn } from "@vueuse/core";
115115
import { useActor } from "@/store/actor";
116116
import { useDataLoaders } from "@/store/dataloader";
117117
import { useModal } from "@/store/modal";
118118
import { useMutationStore } from "@/store/mutation";
119119
import { GetModRequests } from "@/apollo/query/mod-queue.query";
120+
import { NetworkStatus } from "@apollo/client/core/networkStatus";
120121
import { ObjectKind } from "@/structures/Common";
121122
import { Emote } from "@/structures/Emote";
122123
import { Message } from "@/structures/Message";
@@ -152,22 +153,20 @@ const filter = computed(
152153
);
153154
const filterType = ref(false);
154155
155-
const query = useQuery<GetModRequests.Result, GetModRequests.Variables>(
156-
GetModRequests,
157-
() => ({
158-
page: 0,
159-
limit: limit.value,
160-
wish: activeTab.value,
161-
country: CISO2.has(country.value.toUpperCase())
162-
? country.value
163-
: filter.value.size && !filterType.value
164-
? [...filter.value]
165-
: undefined,
166-
}),
167-
{
168-
fetchPolicy: "cache-and-network",
169-
},
170-
);
156+
const vars = computed(() => ({
157+
page: 0,
158+
limit: limit.value,
159+
wish: activeTab.value,
160+
country: CISO2.has(country.value.toUpperCase())
161+
? country.value
162+
: filter.value.size && !filterType.value
163+
? [...filter.value]
164+
: undefined,
165+
}));
166+
167+
const query = useQuery<GetModRequests.Result, GetModRequests.Variables>(GetModRequests, vars, {
168+
fetchPolicy: "cache-and-network",
169+
});
171170
172171
const visible = ref(24);
173172
const end = ref<HTMLElement | null>(null);
@@ -180,7 +179,15 @@ watch(isAtEnd, (v) => {
180179
}
181180
});
182181
183-
const refetch = () => nextTick(query.refetch);
182+
const autoSync = ref(false);
183+
const isSyncing = ref(false);
184+
const autoSyncer = useIntervalFn(async () => {
185+
isSyncing.value = true;
186+
await query.refetch();
187+
isSyncing.value = false;
188+
}, 10000);
189+
autoSyncer.pause();
190+
watch(autoSync, (v) => (v ? autoSyncer.resume() : autoSyncer.pause(), { immediate: true }));
184191
185192
const addMore = async () => {
186193
if (!canViewMore.value) return;
@@ -223,11 +230,13 @@ const searchQuery = ref("");
223230
224231
const debouncedSearch = debouncedRef(searchQuery, 500);
225232
226-
const targetMap = new Map<string, Emote>();
233+
const targetMap = new Map<string, Emote | undefined>();
227234
228235
const loadEmotes = async (ids: string[]) => {
229236
const toLoad = ids.filter((id) => !targetMap.has(id));
230237
if (!toLoad.length) return;
238+
toLoad.forEach((id) => targetMap.set(id, undefined));
239+
231240
const emotes = await dataloaders.loadEmotes(toLoad);
232241
233242
emotes.forEach((emote) => {
@@ -241,8 +250,16 @@ const loadEmotes = async (ids: string[]) => {
241250
});
242251
};
243252
244-
query.onResult(({ data }) => {
253+
const readCards = ref(new Set<string>());
254+
let block = false;
255+
query.onResult(({ data, networkStatus }) => {
256+
if (networkStatus !== NetworkStatus.ready) return;
245257
if (!data) return;
258+
if (block) return;
259+
260+
block = true;
261+
nextTick(() => (block = false));
262+
246263
const d = structuredClone(toRaw(data)) as typeof data;
247264
if (!d?.modRequests?.messages) return;
248265
@@ -259,11 +276,21 @@ query.onResult(({ data }) => {
259276
r.target = emote;
260277
r.author = emote.owner!;
261278
});
262-
visible.value = BASE_VISIBLE;
263-
canViewMore.value = rs.length > BASE_VISIBLE;
264-
requests.value = rs;
265279
266-
loadEmotes(rs.slice(0, BASE_VISIBLE).map((r) => r.target_id));
280+
if (isSyncing.value) {
281+
const new_ids = new Set(rs.map((r) => r.id));
282+
283+
requests.value.forEach((r) => {
284+
if (!new_ids.has(r.id)) {
285+
readCards.value.add(r.id);
286+
}
287+
});
288+
} else {
289+
requests.value = rs;
290+
visible.value = BASE_VISIBLE;
291+
canViewMore.value = rs.length > BASE_VISIBLE;
292+
loadEmotes(rs.slice(0, BASE_VISIBLE).map((r) => r.target_id));
293+
}
267294
});
268295
269296
watch(debouncedSearch, (s) => {
@@ -292,8 +319,6 @@ const modal = useModal();
292319
293320
const m = useMutationStore();
294321
295-
const readCards = ref(new Set<string>());
296-
297322
// Called when a decision on a request is made
298323
const onDecision = async (req: Message.ModRequest, t: string, isUndo?: boolean) => {
299324
readCards.value.delete(req.id);
@@ -338,6 +363,7 @@ const onDecision = async (req: Message.ModRequest, t: string, isUndo?: boolean)
338363
component: EmoteDeleteModal,
339364
props: {
340365
emote: req.target as Emote,
366+
id: req.target_id,
341367
},
342368
events: {
343369
delete: (reason: string) => resolve([true, reason]),

src/views/emote/EmoteDeleteModal.vue

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
<template>
22
<ModalBase width="32em" height="16em" footer-height="3em" @close="emit('close')">
33
<template #heading>
4-
<h2>{{ t("emote.delete_prompt.heading", [emote.name]) }}</h2>
4+
<h2>{{ t("emote.delete_prompt.heading", [emote?.name ?? "*DELETED?"]) }}</h2>
55
</template>
66

77
<template #content>
88
<div class="delete-explain">
9-
<span> {{ t("emote.delete_prompt.notice", [emote.name]) }} </span>
9+
<span> {{ t("emote.delete_prompt.notice", [emote?.name ?? "*DELETED"]) }} </span>
1010
<TextInput
1111
v-model="reason"
1212
:autofocus="true"
1313
autocomplete="off"
1414
:label="t('emote.delete_prompt.reason')"
1515
/>
16+
<span v-if="!emote">
17+
This emote might be deleted already, manually check the
18+
<a v-if="id" :href="`/emotes/${id}`" target="_blank"> emote page </a>
19+
to confirm
20+
</span>
1621
</div>
1722
</template>
1823

@@ -47,7 +52,8 @@ const emit = defineEmits<{
4752
}>();
4853
4954
defineProps<{
50-
emote: Emote;
55+
emote?: Emote;
56+
id?: string;
5157
}>();
5258
5359
const { t } = useI18n();

0 commit comments

Comments
 (0)