From 3eef9490b2fb68795c826a3467874bd61f56a28f Mon Sep 17 00:00:00 2001 From: Natty Date: Thu, 29 Feb 2024 00:26:09 +0100 Subject: [PATCH] Fixed notification filtering and a bunch of bugs --- .../src/entities/sea_orm_active_enums.rs | 32 --- .../entity_ck/src/entities/user_profile.rs | 4 +- ext_calckey_model/migration/src/lib.rs | 2 + ext_calckey_model/src/note_model/data.rs | 2 +- ext_calckey_model/src/notification_model.rs | 6 +- fe_calckey/frontend/client/package.json | 187 +++++++++--------- .../src/components/MagNotifications.vue | 32 ++- .../client/src/components/MagPagination.vue | 50 ++--- .../MkNotificationSettingWindow.vue | 36 ++-- fe_calckey/frontend/client/src/os.ts | 67 +++++-- .../client/src/pages/notifications.vue | 10 +- .../src/pages/settings/notifications.vue | 27 ++- .../client/src/scripts-mag/mag-util.ts | 58 ++++++ .../frontend/client/src/ui/deck/deck-store.ts | 28 +-- .../src/ui/deck/notifications-column.vue | 18 +- .../client/src/widgets/notifications.vue | 18 +- fe_calckey/frontend/locales/en-US.yml | 13 +- .../frontend/magnetar-common/src/index.ts | 13 ++ .../magnetar-common/src/types/UserSelfExt.ts | 2 +- .../magnetar-common/src/types/UserSelfReq.ts | 2 +- .../types/endpoints/GetFollowRequestsSelf.ts | 2 +- .../src/types/endpoints/GetFollowersById.ts | 2 +- .../src/types/endpoints/GetFollowersSelf.ts | 2 +- .../src/types/endpoints/GetFollowingById.ts | 2 +- .../src/types/endpoints/GetFollowingSelf.ts | 2 +- .../src/types/endpoints/GetManyUsersById.ts | 2 +- .../src/types/endpoints/GetNoteById.ts | 2 +- .../src/types/endpoints/GetNotifications.ts | 2 +- .../src/types/endpoints/GetTimeline.ts | 2 +- .../src/types/endpoints/GetUserByAcct.ts | 2 +- .../src/types/endpoints/GetUserById.ts | 2 +- .../src/types/endpoints/GetUserSelf.ts | 2 +- .../src/types/packed/PackUserSelfMaybeAll.ts | 3 +- fe_calckey/frontend/pnpm-lock.yaml | 9 +- magnetar_common/src/util.rs | 2 +- magnetar_sdk/macros/src/lib.rs | 3 +- magnetar_sdk/src/endpoints/user.rs | 2 + magnetar_sdk/src/types/user.rs | 6 +- src/model/data/user.rs | 39 +++- src/model/mod.rs | 2 +- src/model/processing/drive.rs | 2 +- src/model/processing/emoji.rs | 6 +- src/model/processing/user.rs | 22 ++- src/util.rs | 2 +- src/web/pagination.rs | 2 +- 45 files changed, 452 insertions(+), 279 deletions(-) diff --git a/ext_calckey_model/entity_ck/src/entities/sea_orm_active_enums.rs b/ext_calckey_model/entity_ck/src/entities/sea_orm_active_enums.rs index f3dcf9b..fc54542 100644 --- a/ext_calckey_model/entity_ck/src/entities/sea_orm_active_enums.rs +++ b/ext_calckey_model/entity_ck/src/entities/sea_orm_active_enums.rs @@ -153,35 +153,3 @@ pub enum UserProfileFfvisibilityEnum { #[sea_orm(string_value = "public")] Public, } -#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Copy, Serialize, Deserialize)] -#[sea_orm( - rs_type = "String", - db_type = "Enum", - enum_name = "user_profile_mutingnotificationtypes_enum" -)] -pub enum UserProfileMutingnotificationtypesEnum { - #[sea_orm(string_value = "app")] - App, - #[sea_orm(string_value = "follow")] - Follow, - #[sea_orm(string_value = "followRequestAccepted")] - FollowRequestAccepted, - #[sea_orm(string_value = "groupInvited")] - GroupInvited, - #[sea_orm(string_value = "mention")] - Mention, - #[sea_orm(string_value = "pollEnded")] - PollEnded, - #[sea_orm(string_value = "pollVote")] - PollVote, - #[sea_orm(string_value = "quote")] - Quote, - #[sea_orm(string_value = "reaction")] - Reaction, - #[sea_orm(string_value = "receiveFollowRequest")] - ReceiveFollowRequest, - #[sea_orm(string_value = "renote")] - Renote, - #[sea_orm(string_value = "reply")] - Reply, -} diff --git a/ext_calckey_model/entity_ck/src/entities/user_profile.rs b/ext_calckey_model/entity_ck/src/entities/user_profile.rs index 5e3b082..90bd003 100644 --- a/ext_calckey_model/entity_ck/src/entities/user_profile.rs +++ b/ext_calckey_model/entity_ck/src/entities/user_profile.rs @@ -1,7 +1,7 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.10 +use super::sea_orm_active_enums::NotificationTypeEnum; use super::sea_orm_active_enums::UserProfileFfvisibilityEnum; -use super::sea_orm_active_enums::UserProfileMutingnotificationtypesEnum; use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; @@ -51,7 +51,7 @@ pub struct Model { #[sea_orm(column_name = "mutedWords", column_type = "JsonBinary")] pub muted_words: Json, #[sea_orm(column_name = "mutingNotificationTypes")] - pub muting_notification_types: Vec, + pub muting_notification_types: Vec, #[sea_orm(column_name = "noCrawle")] pub no_crawle: bool, #[sea_orm(column_name = "receiveAnnouncementEmail")] diff --git a/ext_calckey_model/migration/src/lib.rs b/ext_calckey_model/migration/src/lib.rs index 138350a..624c372 100644 --- a/ext_calckey_model/migration/src/lib.rs +++ b/ext_calckey_model/migration/src/lib.rs @@ -10,6 +10,7 @@ mod m20240107_224446_generated_is_renote; mod m20240112_215106_remove_pages; mod m20240112_234759_remove_gallery; mod m20240115_212109_remove_poll_vote_notification; +mod m20240228_155051_mag_notification_types_muting; pub struct Migrator; @@ -27,6 +28,7 @@ impl MigratorTrait for Migrator { Box::new(m20240112_215106_remove_pages::Migration), Box::new(m20240112_234759_remove_gallery::Migration), Box::new(m20240115_212109_remove_poll_vote_notification::Migration), + Box::new(m20240228_155051_mag_notification_types_muting::Migration), ] } } diff --git a/ext_calckey_model/src/note_model/data.rs b/ext_calckey_model/src/note_model/data.rs index eebf291..e6cf9d7 100644 --- a/ext_calckey_model/src/note_model/data.rs +++ b/ext_calckey_model/src/note_model/data.rs @@ -62,7 +62,7 @@ impl FromQueryResult for NoteData { let prefix = if prefix.is_empty() { note::Entity.base_prefix() } else { - MagIden::alias(&prefix) + MagIden::alias(prefix) }; Ok(NoteData { diff --git a/ext_calckey_model/src/notification_model.rs b/ext_calckey_model/src/notification_model.rs index 6e567f9..07a1974 100644 --- a/ext_calckey_model/src/notification_model.rs +++ b/ext_calckey_model/src/notification_model.rs @@ -95,7 +95,7 @@ impl NotificationResolver { note_resolver: &NoteResolver, user_resolver: &UserResolver, ) { - q.add_aliased_columns::(¬ification_tbl); + q.add_aliased_columns::(notification_tbl); let notifier_tbl = notification_tbl.join_str(NOTIFIER); q.add_aliased_columns::(¬ifier_tbl); @@ -143,7 +143,7 @@ impl NotificationResolver { self.resolve( &mut query, ¬ification_tbl, - &resolve_options, + resolve_options, &self.note_resolver, &self.user_resolver, ); @@ -183,7 +183,7 @@ impl NotificationResolver { self.resolve( &mut query, ¬ification_tbl, - &resolve_options, + resolve_options, &self.note_resolver, &self.user_resolver, ); diff --git a/fe_calckey/frontend/client/package.json b/fe_calckey/frontend/client/package.json index a647210..65892ea 100644 --- a/fe_calckey/frontend/client/package.json +++ b/fe_calckey/frontend/client/package.json @@ -1,95 +1,96 @@ { - "name": "client", - "private": true, - "scripts": { - "watch": "pnpm vite build --watch --mode development", - "watchRebuild": "pnpm vite build --watch", - "build": "pnpm vite build", - "format": "pnpm prettier --write '**/*.vue'" - }, - "devDependencies": { - "@discordapp/twemoji": "14.1.2", - "@phosphor-icons/web": "^2.0.3", - "@rollup/plugin-alias": "3.1.9", - "@rollup/plugin-json": "4.1.0", - "@rollup/pluginutils": "^4.2.1", - "@types/escape-regexp": "0.0.1", - "@types/glob": "8.1.0", - "@types/gulp": "4.0.11", - "@types/gulp-rename": "2.0.2", - "@types/katex": "0.16.0", - "@types/matter-js": "0.18.2", - "@types/punycode": "2.1.0", - "@types/seedrandom": "3.0.5", - "@types/throttle-debounce": "5.0.0", - "@types/tinycolor2": "1.4.3", - "@types/uuid": "8.3.4", - "@vitejs/plugin-vue": "4.2.3", - "@vue/compiler-sfc": "3.3.4", - "@vue/runtime-core": "3.3.4", - "autobind-decorator": "2.4.0", - "autosize": "5.0.2", - "blurhash": "1.1.5", - "broadcast-channel": "4.19.1", - "browser-image-resizer": "github:misskey-dev/browser-image-resizer", - "calckey-js": "workspace:*", - "chart.js": "4.3.0", - "chartjs-adapter-date-fns": "3.0.0", - "chartjs-chart-matrix": "^2.0.1", - "chartjs-plugin-gradient": "0.6.1", - "chartjs-plugin-zoom": "2.0.1", - "city-timezones": "^1.2.1", - "compare-versions": "5.0.3", - "cropperjs": "2.0.0-beta.2", - "cross-env": "7.0.3", - "cypress": "10.11.0", - "date-fns": "2.30.0", - "emojilib": "github:thatonecalculator/emojilib", - "escape-regexp": "0.0.1", - "eventemitter3": "4.0.7", - "focus-trap": "^7.4.3", - "focus-trap-vue": "^4.0.2", - "gsap": "^3.11.5", - "idb-keyval": "6.2.1", - "insert-text-at-cursor": "0.3.0", - "json5": "2.2.3", - "katex": "0.16.7", - "magnetar-common": "workspace:*", - "matter-js": "0.18.0", - "mfm-js": "0.23.3", - "photoswipe": "5.3.7", - "prettier": "2.8.8", - "prettier-plugin-vue": "1.1.6", - "prismjs": "1.29.0", - "punycode": "2.1.1", - "querystring": "0.2.1", - "rndstr": "1.0.0", - "rollup": "3.23.1", - "s-age": "1.1.2", - "sass": "1.62.1", - "seedrandom": "3.0.5", - "start-server-and-test": "1.15.2", - "strict-event-emitter-types": "2.0.0", - "stringz": "2.1.0", - "swiper": "9.3.2", - "syuilo-password-strength": "0.0.1", - "textarea-caret": "3.1.0", - "three": "0.146.0", - "throttle-debounce": "5.0.0", - "tinycolor2": "1.5.2", - "tsc-alias": "1.8.6", - "tsconfig-paths": "4.2.0", - "twemoji-parser": "14.0.0", - "typescript": "5.1.3", - "unicode-emoji-json": "^0.4.0", - "uuid": "9.0.0", - "vanilla-tilt": "1.8.0", - "vite": "4.3.9", - "vite-plugin-compression": "^0.5.1", - "vue": "3.3.4", - "vue-isyourpasswordsafe": "^2.0.0", - "vue-plyr": "^7.0.0", - "vue3-otp-input": "^0.4.1", - "vuedraggable": "4.1.0" - } + "name": "client", + "private": true, + "scripts": { + "watch": "pnpm vite build --watch --mode development", + "watchRebuild": "pnpm vite build --watch", + "build": "pnpm vite build", + "format": "pnpm prettier --write '**/*.vue'" + }, + "devDependencies": { + "@discordapp/twemoji": "14.1.2", + "@phosphor-icons/web": "^2.0.3", + "@rollup/plugin-alias": "3.1.9", + "@rollup/plugin-json": "4.1.0", + "@rollup/pluginutils": "^4.2.1", + "@types/escape-regexp": "0.0.1", + "@types/glob": "8.1.0", + "@types/gulp": "4.0.11", + "@types/gulp-rename": "2.0.2", + "@types/katex": "0.16.0", + "@types/matter-js": "0.18.2", + "@types/punycode": "2.1.0", + "@types/seedrandom": "3.0.5", + "@types/throttle-debounce": "5.0.0", + "@types/tinycolor2": "1.4.3", + "@types/uuid": "8.3.4", + "@vitejs/plugin-vue": "4.2.3", + "@vue/compiler-sfc": "3.3.4", + "@vue/runtime-core": "3.3.4", + "autobind-decorator": "2.4.0", + "autosize": "5.0.2", + "blurhash": "1.1.5", + "broadcast-channel": "4.19.1", + "browser-image-resizer": "github:misskey-dev/browser-image-resizer", + "calckey-js": "workspace:*", + "chart.js": "4.3.0", + "chartjs-adapter-date-fns": "3.0.0", + "chartjs-chart-matrix": "^2.0.1", + "chartjs-plugin-gradient": "0.6.1", + "chartjs-plugin-zoom": "2.0.1", + "city-timezones": "^1.2.1", + "compare-versions": "5.0.3", + "cropperjs": "2.0.0-beta.2", + "cross-env": "7.0.3", + "cypress": "10.11.0", + "date-fns": "2.30.0", + "emojilib": "github:thatonecalculator/emojilib", + "escape-regexp": "0.0.1", + "eventemitter3": "4.0.7", + "focus-trap": "^7.4.3", + "focus-trap-vue": "^4.0.2", + "gsap": "^3.11.5", + "idb-keyval": "6.2.1", + "insert-text-at-cursor": "0.3.0", + "json5": "2.2.3", + "katex": "0.16.7", + "magnetar-common": "workspace:*", + "matter-js": "0.18.0", + "mfm-js": "0.23.3", + "photoswipe": "5.3.7", + "prettier": "2.8.8", + "prettier-plugin-vue": "1.1.6", + "prismjs": "1.29.0", + "punycode": "2.1.1", + "querystring": "0.2.1", + "rndstr": "1.0.0", + "rollup": "3.23.1", + "s-age": "1.1.2", + "sass": "1.62.1", + "seedrandom": "3.0.5", + "start-server-and-test": "1.15.2", + "strict-event-emitter-types": "2.0.0", + "stringz": "2.1.0", + "swiper": "9.3.2", + "syuilo-password-strength": "0.0.1", + "textarea-caret": "3.1.0", + "three": "0.146.0", + "throttle-debounce": "5.0.0", + "tinycolor2": "1.5.2", + "tsc-alias": "1.8.6", + "tsconfig-paths": "4.2.0", + "twemoji-parser": "14.0.0", + "typescript": "5.1.3", + "unicode-emoji-json": "^0.4.0", + "uuid": "9.0.0", + "vanilla-tilt": "1.8.0", + "vite": "4.3.9", + "vite-plugin-compression": "^0.5.1", + "vue": "3.3.4", + "vue-component-type-helpers": "1.8.27", + "vue-isyourpasswordsafe": "^2.0.0", + "vue-plyr": "^7.0.0", + "vue3-otp-input": "^0.4.1", + "vuedraggable": "4.1.0" + } } diff --git a/fe_calckey/frontend/client/src/components/MagNotifications.vue b/fe_calckey/frontend/client/src/components/MagNotifications.vue index b30c7e7..711936a 100644 --- a/fe_calckey/frontend/client/src/components/MagNotifications.vue +++ b/fe_calckey/frontend/client/src/components/MagNotifications.vue @@ -25,13 +25,13 @@ notification.type === 'Mention' || notification.type === 'Reply') " - :key="notification.id" + :key="'noteNotif' + notification.id" :note="notification.note" :collapsedReply="!!notification.note.parent_note" /> diff --git a/fe_calckey/frontend/client/src/os.ts b/fe_calckey/frontend/client/src/os.ts index 20be7da..f887d97 100644 --- a/fe_calckey/frontend/client/src/os.ts +++ b/fe_calckey/frontend/client/src/os.ts @@ -22,6 +22,7 @@ import { types, } from "magnetar-common"; import { magReactionToLegacy } from "@/scripts-mag/mag-util"; +import { ComponentProps } from "vue-component-type-helpers"; export const pendingApiRequestsCount = ref(0); @@ -307,11 +308,49 @@ export function getUniqueId(): string { return uniqueId++ + ""; } -export async function popup( - component: Component, - props: Record, - events = {}, - disposeEvent?: string +// See https://github.com/misskey-dev/misskey/blob/5f43c2faa2fae3866a9921d81ab43c3b9e8bd222/packages/frontend/src/os.ts#L150 +// We cannot use "vue-component-type-helpers"'s ComponentEmit, because it returns a type intersection, making it useless +// for type checking of emit handlers +// +// We're not sure why the props were picked from T, because it didn't work, so we made it work on $props, which seems to work correctly +type ComponentEmit = T extends new () => { $props: infer Props } + ? [keyof Pick>] extends [never] + ? Record + : EmitsExtractor + : T extends (...args: any) => any + ? ReturnType extends { + [x: string]: any; + __ctx?: { [x: string]: any; props: infer Props }; + } + ? [keyof Pick>] extends [ + never + ] + ? Record + : EmitsExtractor + : never + : never; + +type EmitsExtractor = { + [K in keyof T as K extends `onVnode${string}` + ? never + : K extends `on${infer E}` + ? Uncapitalize + : K extends string + ? never + : K]: T[K]; +}; + +type ComponentPropsRef = { + [K in keyof ComponentProps]: + | ComponentProps[K] + | Ref[K]>; +}; + +export async function popup( + component: C, + props: ComponentPropsRef, + events: Partial> = {} as ComponentEmit, + disposeEvent?: keyof ComponentEmit ) { markRaw(component); @@ -1022,14 +1061,14 @@ export const deckGlobalEvents = new EventEmitter(); /* export function checkExistence(fileData: ArrayBuffer): Promise { - return new Promise((resolve, reject) => { - const data = new FormData(); - data.append('md5', getMD5(fileData)); + return new Promise((resolve, reject) => { + const data = new FormData(); + data.append('md5', getMD5(fileData)); - os.api('drive/files/find-by-hash', { - md5: getMD5(fileData) - }).then(resp => { - resolve(resp.length > 0 ? resp[0] : null); - }); - }); + os.api('drive/files/find-by-hash', { + md5: getMD5(fileData) + }).then(resp => { + resolve(resp.length > 0 ? resp[0] : null); + }); + }); }*/ diff --git a/fe_calckey/frontend/client/src/pages/notifications.vue b/fe_calckey/frontend/client/src/pages/notifications.vue index 1a5d81d..40448ae 100644 --- a/fe_calckey/frontend/client/src/pages/notifications.vue +++ b/fe_calckey/frontend/client/src/pages/notifications.vue @@ -61,7 +61,7 @@ import { computed, ref, watch } from "vue"; import { Virtual } from "swiper"; import { Swiper, SwiperSlide } from "swiper/vue"; -import { notificationTypes } from "calckey-js"; +import { notificationTypes, types } from "magnetar-common"; import XNotifications from "@/components/MagNotifications.vue"; import XNotes from "@/components/MkNotes.vue"; import * as os from "@/os"; @@ -76,7 +76,7 @@ const tabs = ["all", "unread", "mentions", "directNotes"]; let tab = $ref(tabs[0]); watch($$(tab), () => syncSlide(tabs.indexOf(tab))); -let includeTypes = $ref(null); +let includeTypes = $ref(); let unreadOnly = $computed(() => tab === "unread"); os.api("notifications/mark-all-as-read"); @@ -104,7 +104,7 @@ const directNotesPagination = { function setFilter(ev) { const typeItems = notificationTypes.map((t) => ({ - text: i18n.t(`_notification._types.${t}`), + text: i18n.t(`_notification._magTypes.${t}`), active: includeTypes && includeTypes.includes(t), action: () => { includeTypes = [t]; @@ -117,7 +117,7 @@ function setFilter(ev) { icon: "ph-x ph-bold ph-lg", text: i18n.ts.clear, action: () => { - includeTypes = null; + includeTypes = undefined; }, }, null, @@ -191,6 +191,6 @@ function onSlideChange() { } function syncSlide(index) { - swiperRef.slideTo(index); + swiperRef?.slideTo(index); } diff --git a/fe_calckey/frontend/client/src/pages/settings/notifications.vue b/fe_calckey/frontend/client/src/pages/settings/notifications.vue index 42bcedf..74439fa 100644 --- a/fe_calckey/frontend/client/src/pages/settings/notifications.vue +++ b/fe_calckey/frontend/client/src/pages/settings/notifications.vue @@ -47,7 +47,6 @@