-
Notifications
You must be signed in to change notification settings - Fork 244
Alert user to packages of concern #2074
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feature/unlisted-notifications/tracking
Are you sure you want to change the base?
Changes from all commits
8cf85ac
51e511d
767e4aa
512f932
b87d79d
5fef9c3
df92b23
a1a5edc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| <script setup lang="ts"> | ||
|
|
||
| import { getStore } from '@r2/providers/generic/store/StoreProvider'; | ||
| import { State } from '@r2/store'; | ||
| import { useConcerningPackageComposable } from '@r2/components/composables/ConcerningPackageComposable'; | ||
|
|
||
| const store = getStore<State>(); | ||
| const { hasConcerningPackages } = useConcerningPackageComposable(); | ||
|
|
||
| function addUnlinkedFilter() { | ||
| store.commit('profile/scopeLocalModListToUnlinkedPackages'); | ||
| } | ||
| </script> | ||
|
|
||
| <template> | ||
| <div class="notification is-concern margin-right" v-show="hasConcerningPackages"> | ||
| <span>You have packages that can no longer be found on Thunderstore.</span> <a href="#" @click.stop.prevent="addUnlinkedFilter">Click here to review packages.</a> | ||
| </div> | ||
| </template> | ||
|
|
||
| <style scoped lang="scss"> | ||
| .is-concern { | ||
| background-color: var(--notification-concern-background-color); | ||
| color: var(--notification-concern-text-color); | ||
| } | ||
|
|
||
| .notification { | ||
| margin-bottom: 0.5rem; | ||
| } | ||
| </style> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| /** | ||
| * Definitions are outside the composable function so that calculations are shared. | ||
| * We do not need to recalculate on a per-usage basis. | ||
| */ | ||
| import { getStore } from '@r2/providers/generic/store/StoreProvider'; | ||
| import { computed, ref, watch } from 'vue'; | ||
| import ManifestV2 from '@r2/model/ManifestV2'; | ||
| import ThunderstoreMod from '@r2/model/ThunderstoreMod'; | ||
|
|
||
| const store = getStore<any>(); | ||
|
|
||
| const localModList = computed<ManifestV2[]>(() => store.state.profile.modList); | ||
| const onlineModList = computed<Map<string, ThunderstoreMod>>(() => { | ||
| const mods: ThunderstoreMod[] = store.state.tsMods.mods; | ||
| return new Map<string, ThunderstoreMod>(mods.map(value => [value.getFullName(), value])); | ||
| }); | ||
|
|
||
| const concerningPackages = computed<ManifestV2[]>(() => { | ||
| return localModList.value.filter(value => !value.isTrustedPackage() && (value.isOnlineSource() && !onlineModList.value.has(value.getName()))); | ||
| }); | ||
|
|
||
| export function useConcerningPackageComposable() { | ||
|
|
||
| const hasConcerningPackages = computed<boolean>(() => concerningPackages.value.length > 0); | ||
|
|
||
| function isConcerningPackage(mod: ManifestV2) { | ||
| return concerningPackages.value.findIndex(value => value.getName() === mod.getName()) >= 0; | ||
| } | ||
|
|
||
| return { | ||
| concerningPackages, | ||
| hasConcerningPackages, | ||
| isConcerningPackage | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import { getStore } from '@r2/providers/generic/store/StoreProvider'; | ||
| import Dependants from '@r2/r2mm/mods/Dependants'; | ||
| import R2Error from '@r2/model/errors/R2Error'; | ||
| import { LogSeverity } from '@r2/providers/ror2/logging/LoggerProvider'; | ||
| import ManifestV2 from '@r2/model/ManifestV2'; | ||
|
|
||
| const store = getStore<any>(); | ||
|
|
||
| export function useModManagementComposable() { | ||
|
|
||
| async function uninstallMod(mod: ManifestV2) { | ||
| const dependants = Dependants.getDependantList(mod, store.state.profile.modList); | ||
|
|
||
| if (dependants.size > 0) { | ||
| store.commit('openUninstallModModal', mod); | ||
| return; | ||
| } | ||
|
|
||
| try { | ||
| await store.dispatch( | ||
| 'profile/uninstallModsFromActiveProfile', | ||
| { mods: [mod] } | ||
| ); | ||
| } catch (e) { | ||
| store.commit('error/handleError', { | ||
| error: R2Error.fromThrownValue(e), | ||
| severity: LogSeverity.ACTION_STOPPED | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| return { | ||
| uninstallMod | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| <script setup lang="ts"> | ||
| import { computed } from 'vue'; | ||
| import ModalCard from '@r2/components/ModalCard.vue'; | ||
| import { State } from '@r2/store'; | ||
| import { getStore } from '@r2/providers/generic/store/StoreProvider'; | ||
| import ManifestV2 from '@r2/model/ManifestV2'; | ||
| import { useModManagementComposable } from '@r2/components/composables/ModManagementComposable'; | ||
| import R2Error from '@r2/model/errors/R2Error'; | ||
| import ProfileModList from '@r2/r2mm/mods/ProfileModList'; | ||
|
|
||
| const store = getStore<State>(); | ||
|
|
||
| const { uninstallMod } = useModManagementComposable(); | ||
|
|
||
| const isOpen = computed(() => store.state.modals.isConcerningModReviewModalOpen); | ||
| const modToReview = computed<ManifestV2 | null>(() => store.state.modals.concerningModToReview); | ||
| const profile = computed(() => store.getters['profile/activeProfile']); | ||
|
|
||
| function close() { | ||
| store.commit('closeConcerningModReviewModal'); | ||
| } | ||
|
|
||
| async function removeMod() { | ||
| await uninstallMod(modToReview.value!); | ||
| close(); | ||
| } | ||
|
|
||
| async function trustPackage() { | ||
| const mods = await ProfileModList.getModList(profile.value.asImmutableProfile()); | ||
| if (mods instanceof R2Error) { | ||
| console.error(mods); | ||
| store.commit('error/handleError', mods); | ||
| return; | ||
| } | ||
| const mod = mods.find(value => value.getName() === modToReview.value?.getName()); | ||
| if (mod) { | ||
| mod.setTrustedPackage(true); | ||
| } | ||
| try { | ||
| const err = await ProfileModList.saveModList(profile.value.asImmutableProfile(), mods); | ||
| if (err instanceof R2Error) { | ||
| store.commit('error/handleError', err); | ||
| return; | ||
| } | ||
| await store.dispatch('profile/updateModList', mods); | ||
| } catch (e) { | ||
| store.commit('error/handleError', R2Error.fromThrownValue(e)); | ||
| } finally { | ||
| close(); | ||
| } | ||
| } | ||
| </script> | ||
|
|
||
| <template> | ||
| <ModalCard id="review-package-modal" v-if="isOpen && modToReview" :is-active="isOpen" :can-close="true" @close-modal="close"> | ||
| <template v-slot:header> | ||
| <h2 class="modal-title">Review {{ modToReview.getName() }}</h2> | ||
| </template> | ||
| <template v-slot:body> | ||
| <p class="notification is-warning">It is generally recommended to remove mods that have been removed from Thunderstore.</p> | ||
| <div> | ||
| <hr/> | ||
| <p class="margin-bottom">This mod was originally downloaded using the Online section however no longer appears in the package cache.</p> | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I would reword this whole section to this: |
||
| <p class="margin-bottom">When a mod is no longer in the package cache, it means that it has been removed from Thunderstore.</p> | ||
| <p>Other people will be unable to import this mod if the profile is exported.</p> | ||
| </div> | ||
| </template> | ||
| <template v-slot:footer> | ||
| <button class="button" @click.stop.prevent="trustPackage"> | ||
| Mark version as safe | ||
| </button> | ||
| <button class="button is-danger" @click.stop.prevent="removeMod"> | ||
| Remove mod | ||
| </button> | ||
| </template> | ||
| </ModalCard> | ||
| </template> | ||
|
|
||
| <style scoped lang="scss"> | ||
|
|
||
| </style> | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might as well call it a "mod" everywhere since that's what we do elsewhere in the mod manager.