mirror of
https://github.com/sbondCo/Watcharr.git
synced 2026-08-07 07:14:44 +00:00
Filtering: Add includePreviouslyWatched setting
This commit is contained in:
@@ -80,6 +80,10 @@ type UserSettings struct {
|
||||
PrivateThoughts *bool `gorm:"default:false" json:"privateThoughts"`
|
||||
// If ui 'spoilers' should be shown
|
||||
HideSpoilers *bool `gorm:"default:false" json:"hideSpoilers"`
|
||||
// If user wants previously watched items to show in 'Finished' filter,
|
||||
// even if the watched item state has since been changed. Used only in
|
||||
// frontend.
|
||||
IncludePreviouslyWatched *bool `gorm:"default:false" json:"includePreviouslyWatched"`
|
||||
}
|
||||
|
||||
// We use a separate struct for registration to avoid confusion
|
||||
|
||||
+15
-2
@@ -55,8 +55,16 @@ func userUpdate(db *gorm.DB, userId uint, ur UserSettings) (UserSettings, error)
|
||||
if ur.PrivateThoughts != nil {
|
||||
user.PrivateThoughts = ur.PrivateThoughts
|
||||
}
|
||||
if ur.IncludePreviouslyWatched != nil {
|
||||
user.IncludePreviouslyWatched = ur.IncludePreviouslyWatched
|
||||
}
|
||||
db.Save(&user)
|
||||
return UserSettings{Private: user.Private, PrivateThoughts: user.PrivateThoughts, HideSpoilers: user.HideSpoilers}, nil
|
||||
return UserSettings{
|
||||
Private: user.Private,
|
||||
PrivateThoughts: user.PrivateThoughts,
|
||||
HideSpoilers: user.HideSpoilers,
|
||||
IncludePreviouslyWatched: user.IncludePreviouslyWatched,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func userGetSettings(db *gorm.DB, userId uint) (UserSettings, error) {
|
||||
@@ -67,7 +75,12 @@ func userGetSettings(db *gorm.DB, userId uint) (UserSettings, error) {
|
||||
slog.Error("user get failed", "user_id", userId, "error", res.Error)
|
||||
return UserSettings{}, errors.New("failed to retrieve user")
|
||||
}
|
||||
return UserSettings{Private: user.Private, PrivateThoughts: user.PrivateThoughts, HideSpoilers: user.HideSpoilers}, nil
|
||||
return UserSettings{
|
||||
Private: user.Private,
|
||||
PrivateThoughts: user.PrivateThoughts,
|
||||
HideSpoilers: user.HideSpoilers,
|
||||
IncludePreviouslyWatched: user.IncludePreviouslyWatched,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func userSearch(db *gorm.DB, currentUsersId uint, q string) ([]PublicUser, error) {
|
||||
|
||||
+63
-15
@@ -3,7 +3,7 @@
|
||||
import Icon from "@/lib/Icon.svelte";
|
||||
import Poster from "@/lib/poster/Poster.svelte";
|
||||
import PosterList from "@/lib/poster/PosterList.svelte";
|
||||
import { activeFilters, activeSort } from "@/store";
|
||||
import { activeFilters, activeSort, userSettings } from "@/store";
|
||||
import type { Watched, WatchedSeason } from "@/types";
|
||||
|
||||
export let list: Watched[];
|
||||
@@ -11,8 +11,39 @@
|
||||
|
||||
$: sort = $activeSort;
|
||||
$: filters = $activeFilters;
|
||||
$: watched = list
|
||||
.sort((a, b) => {
|
||||
$: watched = list;
|
||||
$: settings = $userSettings;
|
||||
|
||||
function contentWatchedPreviously(w: Watched) {
|
||||
let wp = false;
|
||||
const relatedActivity = w.activity.filter(
|
||||
(a) =>
|
||||
a.type === "ADDED_WATCHED" ||
|
||||
a.type === "IMPORTED_ADDED_WATCHED" ||
|
||||
a.type === "IMPORTED_WATCHED"
|
||||
);
|
||||
for (let i = 0; i < relatedActivity.length; i++) {
|
||||
const ra = relatedActivity[i];
|
||||
if (ra.type === "IMPORTED_ADDED_WATCHED") {
|
||||
wp = true;
|
||||
break;
|
||||
} else if (ra.type === "ADDED_WATCHED" || ra.type === "IMPORTED_WATCHED") {
|
||||
const data = JSON.parse(ra.data);
|
||||
if (data?.status == "FINISHED") {
|
||||
wp = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return wp;
|
||||
}
|
||||
|
||||
// Monsterous code for filters. Soz.
|
||||
$: (watched, filters), filt();
|
||||
|
||||
function filt() {
|
||||
// Set watched to list and sort it.
|
||||
watched = list.sort((a, b) => {
|
||||
if (sort[0] === "DATEADDED" && sort[1] === "UP") {
|
||||
return Date.parse(a.createdAt) - Date.parse(b.createdAt);
|
||||
} else if (sort[0] === "ALPHA") {
|
||||
@@ -27,21 +58,38 @@
|
||||
}
|
||||
// default DATEADDED DOWN
|
||||
return Date.parse(b.createdAt) - Date.parse(a.createdAt);
|
||||
})
|
||||
.filter((w) => {
|
||||
if (filters.status.length <= 0 && filters.type.length <= 0) return w;
|
||||
if (filters.status.length > 0 && filters.type.length > 0) {
|
||||
return (
|
||||
filters.status.includes(w.status?.toLowerCase()) && filters.type.includes(w.content.type)
|
||||
});
|
||||
// Now apply filters to watch list.
|
||||
if (filters.status.length > 0 && filters.type.length > 0) {
|
||||
// If status and type filters applied, combine both.
|
||||
if (settings?.includePreviouslyWatched && filters.status.includes("finished")) {
|
||||
watched = watched.filter(
|
||||
(w) =>
|
||||
(filters.status.includes(w.status?.toLowerCase()) &&
|
||||
filters.type.includes(w.content.type)) ||
|
||||
contentWatchedPreviously(w)
|
||||
);
|
||||
} else {
|
||||
watched = watched.filter(
|
||||
(w) =>
|
||||
filters.status.includes(w.status?.toLowerCase()) &&
|
||||
filters.type.includes(w.content.type)
|
||||
);
|
||||
}
|
||||
if (filters.type.length > 0) {
|
||||
return filters.type.includes(w.content.type);
|
||||
} else if (filters.type.length > 0) {
|
||||
// Only filter type
|
||||
watched = watched.filter((w) => filters.type.includes(w.content.type));
|
||||
} else if (filters.status.length > 0) {
|
||||
// Only filter status
|
||||
if (settings?.includePreviouslyWatched && filters.status.includes("finished")) {
|
||||
watched = watched.filter(
|
||||
(w) => filters.status.includes(w.status?.toLowerCase()) || contentWatchedPreviously(w)
|
||||
);
|
||||
} else {
|
||||
watched = watched.filter((w) => filters.status.includes(w.status?.toLowerCase()));
|
||||
}
|
||||
if (filters.status.length > 0) {
|
||||
return filters.status.includes(w.status?.toLowerCase());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Get biggest season watching or biggest season watched.
|
||||
// This could probably be simpler but -_-
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
let privateThoughtsDisabled = false;
|
||||
let exportDisabled = false;
|
||||
let hideSpoilersDisabled = false;
|
||||
let includePreviouslyWatchedDisabled = false;
|
||||
let pwChangeModalOpen = false;
|
||||
|
||||
async function getProfile() {
|
||||
@@ -236,6 +237,24 @@
|
||||
}}
|
||||
/>
|
||||
</Setting>
|
||||
|
||||
<Setting
|
||||
title="Include Previously Watched"
|
||||
desc="Do you want to include previously watched content in the 'finished' filter, even if their status has now been changed?"
|
||||
row
|
||||
>
|
||||
<Checkbox
|
||||
name="includePreviouslyWatched"
|
||||
disabled={includePreviouslyWatchedDisabled}
|
||||
value={settings?.includePreviouslyWatched}
|
||||
toggled={(on) => {
|
||||
includePreviouslyWatchedDisabled = true;
|
||||
updateUserSetting("includePreviouslyWatched", on, () => {
|
||||
includePreviouslyWatchedDisabled = false;
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Setting>
|
||||
<div class="row btns">
|
||||
<button on:click={() => goto("/import")}>Import</button>
|
||||
<button on:click={() => downloadWatchedList()} disabled={exportDisabled}>Export</button>
|
||||
|
||||
@@ -120,6 +120,7 @@ export interface UserSettings {
|
||||
private: boolean;
|
||||
privateThoughts: boolean;
|
||||
hideSpoilers: boolean;
|
||||
includePreviouslyWatched: boolean;
|
||||
}
|
||||
|
||||
export interface ChangePasswordForm {
|
||||
|
||||
Reference in New Issue
Block a user