Merge pull request #3572 from rommapp/feat/v2-remove-from-continue-playing

feat(v2): restore "remove from continue playing" action
This commit is contained in:
Zurdi
2026-06-21 23:41:28 +02:00
committed by GitHub
19 changed files with 78 additions and 0 deletions

View File

@@ -219,6 +219,8 @@
"single-player": "Един играч",
"snackbar-download-link-copied": "Линкът за сваляне е копиран в клипборда",
"snackbar-link-copied": "Линкът е копиран в клипборда",
"snackbar-removed-from-playing": "Removed from Continue Playing",
"snackbar-remove-from-playing-failed": "Failed to remove from Continue Playing",
"snackbar-update-field-failed": "Неуспешно обновяване на {field}",
"snackbar-update-status-failed": "Неуспешно обновяване на статуса",
"status-active-count": "Статус: {count} активни",

View File

@@ -219,6 +219,8 @@
"single-player": "Pro jednoho hráče",
"snackbar-download-link-copied": "Odkaz ke stažení zkopírován do schránky",
"snackbar-link-copied": "Odkaz zkopírován do schránky",
"snackbar-removed-from-playing": "Removed from Continue Playing",
"snackbar-remove-from-playing-failed": "Failed to remove from Continue Playing",
"snackbar-update-field-failed": "Nepodařilo se aktualizovat {field}",
"snackbar-update-status-failed": "Nepodařilo se aktualizovat stav",
"status-active-count": "Stav: {count} aktivních",

View File

@@ -219,6 +219,8 @@
"single-player": "Einzelspieler",
"snackbar-download-link-copied": "Download-Link in die Zwischenablage kopiert",
"snackbar-link-copied": "Link in die Zwischenablage kopiert",
"snackbar-removed-from-playing": "Vom Spielen entfernt",
"snackbar-remove-from-playing-failed": "Entfernen vom Spielen fehlgeschlagen",
"snackbar-update-field-failed": "{field} konnte nicht aktualisiert werden",
"snackbar-update-status-failed": "Status konnte nicht aktualisiert werden",
"status-active-count": "Status: {count} aktiv",

View File

@@ -219,6 +219,8 @@
"single-player": "Single player",
"snackbar-download-link-copied": "Download link copied to clipboard",
"snackbar-link-copied": "Link copied to clipboard",
"snackbar-removed-from-playing": "Removed from Continue Playing",
"snackbar-remove-from-playing-failed": "Failed to remove from Continue Playing",
"snackbar-update-field-failed": "Failed to update {field}",
"snackbar-update-status-failed": "Failed to update status",
"status-active-count": "Status: {count} active",

View File

@@ -219,6 +219,8 @@
"single-player": "Single player",
"snackbar-download-link-copied": "Download link copied to clipboard",
"snackbar-link-copied": "Link copied to clipboard",
"snackbar-removed-from-playing": "Removed from Continue Playing",
"snackbar-remove-from-playing-failed": "Failed to remove from Continue Playing",
"snackbar-update-field-failed": "Failed to update {field}",
"snackbar-update-status-failed": "Failed to update status",
"status-active-count": "Status: {count} active",

View File

@@ -328,6 +328,8 @@
"single-player": "Un jugador",
"snackbar-download-link-copied": "Enlace de descarga copiado al portapapeles",
"snackbar-link-copied": "Enlace copiado al portapapeles",
"snackbar-removed-from-playing": "Eliminado de jugar",
"snackbar-remove-from-playing-failed": "Error al eliminar de jugar",
"snackbar-update-field-failed": "Error al actualizar {field}",
"snackbar-update-status-failed": "Error al actualizar el estado",
"status-active-count": "Estado: {count} activos",

View File

@@ -219,6 +219,8 @@
"single-player": "Solo",
"snackbar-download-link-copied": "Lien de téléchargement copié dans le presse-papiers",
"snackbar-link-copied": "Lien copié dans le presse-papiers",
"snackbar-removed-from-playing": "Retiré des jeux en cours",
"snackbar-remove-from-playing-failed": "Échec du retrait des jeux en cours",
"snackbar-update-field-failed": "Échec de la mise à jour de {field}",
"snackbar-update-status-failed": "Échec de la mise à jour du statut",
"status-active-count": "Statut : {count} actif(s)",

View File

@@ -219,6 +219,8 @@
"single-player": "Egyjátékos",
"snackbar-download-link-copied": "Letöltési link a vágólapra másolva",
"snackbar-link-copied": "Link a vágólapra másolva",
"snackbar-removed-from-playing": "Removed from Continue Playing",
"snackbar-remove-from-playing-failed": "Failed to remove from Continue Playing",
"snackbar-update-field-failed": "A(z) {field} frissítése sikertelen",
"snackbar-update-status-failed": "Az állapot frissítése sikertelen",
"status-active-count": "Állapot: {count} aktív",

View File

@@ -219,6 +219,8 @@
"single-player": "Giocatore singolo",
"snackbar-download-link-copied": "Link per il download copiato negli appunti",
"snackbar-link-copied": "Link copiato negli appunti",
"snackbar-removed-from-playing": "Rimosso da Stai giocando",
"snackbar-remove-from-playing-failed": "Impossibile rimuovere da Stai giocando",
"snackbar-update-field-failed": "Impossibile aggiornare {field}",
"snackbar-update-status-failed": "Impossibile aggiornare lo stato",
"status-active-count": "Stato: {count} attivi",

View File

@@ -219,6 +219,8 @@
"single-player": "シングルプレイヤー",
"snackbar-download-link-copied": "ダウンロードリンクをクリップボードにコピーしました",
"snackbar-link-copied": "リンクをクリップボードにコピーしました",
"snackbar-removed-from-playing": "Removed from Continue Playing",
"snackbar-remove-from-playing-failed": "Failed to remove from Continue Playing",
"snackbar-update-field-failed": "{field}の更新に失敗しました",
"snackbar-update-status-failed": "ステータスの更新に失敗しました",
"status-active-count": "ステータス: {count}件有効",

View File

@@ -219,6 +219,8 @@
"single-player": "싱글플레이어",
"snackbar-download-link-copied": "다운로드 링크가 클립보드에 복사되었습니다",
"snackbar-link-copied": "링크가 클립보드에 복사되었습니다",
"snackbar-removed-from-playing": "Removed from Continue Playing",
"snackbar-remove-from-playing-failed": "Failed to remove from Continue Playing",
"snackbar-update-field-failed": "{field} 업데이트에 실패했습니다",
"snackbar-update-status-failed": "상태 업데이트에 실패했습니다",
"status-active-count": "상태: {count}개 활성",

View File

@@ -219,6 +219,8 @@
"single-player": "Jednoosobowa",
"snackbar-download-link-copied": "Link do pobrania skopiowany do schowka",
"snackbar-link-copied": "Link skopiowany do schowka",
"snackbar-removed-from-playing": "Removed from Continue Playing",
"snackbar-remove-from-playing-failed": "Failed to remove from Continue Playing",
"snackbar-update-field-failed": "Nie udało się zaktualizować {field}",
"snackbar-update-status-failed": "Nie udało się zaktualizować statusu",
"status-active-count": "Status: {count} aktywnych",

View File

@@ -219,6 +219,8 @@
"single-player": "Um jogador",
"snackbar-download-link-copied": "Link de download copiado para a área de transferência",
"snackbar-link-copied": "Link copiado para a área de transferência",
"snackbar-removed-from-playing": "Removido de jogando",
"snackbar-remove-from-playing-failed": "Falha ao remover de jogando",
"snackbar-update-field-failed": "Falha ao atualizar {field}",
"snackbar-update-status-failed": "Falha ao atualizar o status",
"status-active-count": "Status: {count} ativos",

View File

@@ -219,6 +219,8 @@
"single-player": "Singur jucător",
"snackbar-download-link-copied": "Linkul de descărcare a fost copiat în clipboard",
"snackbar-link-copied": "Linkul a fost copiat în clipboard",
"snackbar-removed-from-playing": "Removed from Continue Playing",
"snackbar-remove-from-playing-failed": "Failed to remove from Continue Playing",
"snackbar-update-field-failed": "Actualizarea câmpului {field} a eșuat",
"snackbar-update-status-failed": "Actualizarea stării a eșuat",
"status-active-count": "Stare: {count} active",

View File

@@ -219,6 +219,8 @@
"single-player": "Одиночная игра",
"snackbar-download-link-copied": "Ссылка для скачивания скопирована в буфер обмена",
"snackbar-link-copied": "Ссылка скопирована в буфер обмена",
"snackbar-removed-from-playing": "Удалено из играющих",
"snackbar-remove-from-playing-failed": "Не удалось удалить из играющих",
"snackbar-update-field-failed": "Не удалось обновить {field}",
"snackbar-update-status-failed": "Не удалось обновить статус",
"status-active-count": "Статус: {count} активных",

View File

@@ -219,6 +219,8 @@
"single-player": "单人",
"snackbar-download-link-copied": "下载链接已复制到剪贴板",
"snackbar-link-copied": "链接已复制到剪贴板",
"snackbar-removed-from-playing": "Removed from Continue Playing",
"snackbar-remove-from-playing-failed": "Failed to remove from Continue Playing",
"snackbar-update-field-failed": "更新 {field} 失败",
"snackbar-update-status-failed": "更新状态失败",
"status-active-count": "状态:{count} 个已激活",

View File

@@ -219,6 +219,8 @@
"single-player": "單人",
"snackbar-download-link-copied": "下載連結已複製到剪貼簿",
"snackbar-link-copied": "連結已複製到剪貼簿",
"snackbar-removed-from-playing": "Removed from Continue Playing",
"snackbar-remove-from-playing-failed": "Failed to remove from Continue Playing",
"snackbar-update-field-failed": "更新 {field} 失敗",
"snackbar-update-status-failed": "更新狀態失敗",
"status-active-count": "狀態:{count} 個啟用",

View File

@@ -72,6 +72,12 @@ function run(fn: () => void | Promise<void>) {
icon="mdi-bookmark-outline"
@click="run(actions.manageCollections)"
/>
<RMenuItem
v-if="actions.canRemoveFromContinuePlaying.value"
:label="t('rom.remove-from-playing')"
icon="mdi-play-protected-content"
@click="run(actions.removeFromContinuePlaying)"
/>
<RDivider />

View File

@@ -16,6 +16,7 @@ import { useRouter } from "vue-router";
import type { RomUserData, RomUserStatus } from "@/__generated__";
import { useFavoriteToggle } from "@/composables/useFavoriteToggle";
import romApi from "@/services/api/rom";
import storeAuth from "@/stores/auth";
import storeRoms from "@/stores/roms";
import type { SimpleRom } from "@/stores/roms";
import type { Events } from "@/types/emitter";
@@ -31,6 +32,7 @@ export function useGameActions(getRom: () => SimpleRom | null | undefined) {
const emitter = inject<Emitter<Events>>("emitter");
const snackbar = useSnackbar();
const romsStore = storeRoms();
const auth = storeAuth();
const canCreateCollection = useCan("collection.create");
const canEditCollection = useCan("collection.edit");
const { isFavorite, toggleFavorite } = useFavoriteToggle(emitter);
@@ -279,11 +281,46 @@ export function useGameActions(getRom: () => SimpleRom | null | undefined) {
emitter?.emit("showDeleteRomDialog", [rom]);
}
// Only relevant while the ROM carries a `last_played` timestamp — i.e.
// it currently sits in the Continue Playing row. Also requires the
// `roms.user.write` scope to match the backend gate and avoid a 403.
const canRemoveFromContinuePlaying = computed(
() =>
auth.scopes.includes("roms.user.write") &&
Boolean(getRom()?.rom_user?.last_played),
);
// Clears the per-user `last_played` so the ROM drops out of Continue
// Playing. Mirrors v1's AdminMenu.resetLastPlayed: update the backend,
// wipe the local timestamp, and prune the cached continue-playing list.
async function removeFromContinuePlaying() {
const rom = getRom();
if (!rom) return;
try {
await romApi.updateUserRomProps({
romId: rom.id,
data: {},
removeLastPlayed: true,
});
if (rom.rom_user) rom.rom_user.last_played = null;
romsStore.update(rom);
romsStore.removeFromContinuePlaying(rom);
snackbar.success(t("rom.snackbar-removed-from-playing"), {
icon: "mdi-check-bold",
});
} catch {
snackbar.error(t("rom.snackbar-remove-from-playing-failed"), {
icon: "mdi-alert-circle-outline",
});
}
}
return {
isFavorited,
canManageCollections,
canShareQR,
canPlay,
canRemoveFromContinuePlaying,
currentStatusKey,
setStatus,
setStatusEnum,
@@ -301,5 +338,6 @@ export function useGameActions(getRom: () => SimpleRom | null | undefined) {
edit,
match,
remove,
removeFromContinuePlaying,
};
}