refactor: unify pref endpoints

This commit is contained in:
2026-04-09 14:23:33 +03:00
parent 735f60d226
commit 3864426c05
6 changed files with 410 additions and 1297 deletions

View File

@@ -20,9 +20,8 @@ use OCP\IRequest;
use OCP\IUserSession;
/**
* @psalm-import-type PantryLastHouse from ResponseDefinitions
* @psalm-import-type PantryImageFolder from ResponseDefinitions
* @psalm-import-type PantryNotificationPrefs from ResponseDefinitions
* @psalm-import-type PantryUserPrefs from ResponseDefinitions
* @psalm-import-type PantryHousePrefs from ResponseDefinitions
*/
final class PrefsController extends OCSController {
use TranslatesDomainExceptions;
@@ -38,252 +37,90 @@ final class PrefsController extends OCSController {
}
/**
* Get the current user's last-used house id
* Get all user-level preferences (not scoped to a house)
*
* @return DataResponse<Http::STATUS_OK, PantryLastHouse, array{}>
* @return DataResponse<Http::STATUS_OK, PantryUserPrefs, array{}>
*
* 200: Last house returned
* 200: Prefs returned
*/
#[ApiRoute(verb: 'GET', url: '/api/prefs/last-house')]
#[ApiRoute(verb: 'GET', url: '/api/prefs')]
#[NoAdminRequired]
public function getLastHouse(): DataResponse {
public function getUserPrefs(): DataResponse {
return $this->runAction(function (): DataResponse {
$uid = $this->requireUid();
$houseId = $this->prefs->getLastHouseId($uid);
$prefs = $this->prefs->getAllUserPrefs($uid);
// If the saved house is no longer accessible, forget it.
$houseId = $prefs['lastHouseId'] ?? null;
if ($houseId !== null) {
try {
$this->auth->requireMember($houseId, $uid);
} catch (ForbiddenException) {
$this->prefs->setLastHouseId($uid, null);
$houseId = null;
$prefs['lastHouseId'] = null;
}
}
return new DataResponse(['houseId' => $houseId]);
return new DataResponse($prefs);
});
}
/**
* Set the current user's last-used house id
* Update user-level preferences
*
* @param int|null $houseId House id, or null to clear.
* @param int|null $lastHouseId Last-used house id, or null to clear.
*
* @return DataResponse<Http::STATUS_OK, PantryLastHouse, array{}>
* @return DataResponse<Http::STATUS_OK, PantryUserPrefs, array{}>
*
* 200: Last house updated
* 200: Prefs updated
*/
#[ApiRoute(verb: 'PUT', url: '/api/prefs/last-house')]
#[ApiRoute(verb: 'PUT', url: '/api/prefs')]
#[NoAdminRequired]
public function setLastHouse(?int $houseId = null): DataResponse {
return $this->runAction(function () use ($houseId): DataResponse {
public function setUserPrefs(?int $lastHouseId = null): DataResponse {
return $this->runAction(function () use ($lastHouseId): DataResponse {
$uid = $this->requireUid();
if ($houseId !== null) {
$this->auth->requireMember($houseId, $uid);
$patch = [];
if ($lastHouseId !== null) {
$this->auth->requireMember($lastHouseId, $uid);
$patch['lastHouseId'] = $lastHouseId;
} else {
// Explicit null means clear
$patch['lastHouseId'] = null;
}
$this->prefs->setLastHouseId($uid, $houseId);
return new DataResponse(['houseId' => $houseId]);
$this->prefs->setUserPrefs($uid, $patch);
return new DataResponse($this->prefs->getAllUserPrefs($uid));
});
}
/**
* Get the user's preferred image upload folder for a house
* Get all per-house preferences for the current user
*
* @param int $houseId House id.
*
* @return DataResponse<Http::STATUS_OK, PantryImageFolder, array{}>
*
* 200: Folder returned
*/
#[ApiRoute(verb: 'GET', url: '/api/houses/{houseId}/prefs/image-folder')]
#[NoAdminRequired]
public function getImageFolder(int $houseId): DataResponse {
return $this->runAction(function () use ($houseId): DataResponse {
$uid = $this->requireUid();
$this->auth->requireMember($houseId, $uid);
return new DataResponse(['folder' => $this->prefs->getImageFolder($uid, $houseId)]);
});
}
/**
* Set the user's preferred image upload folder for a house
*
* @param int $houseId House id.
* @param string $folder Absolute path within the user's files.
*
* @return DataResponse<Http::STATUS_OK, PantryImageFolder, array{}>
*
* 200: Folder updated
*/
#[ApiRoute(verb: 'PUT', url: '/api/houses/{houseId}/prefs/image-folder')]
#[NoAdminRequired]
public function setImageFolder(int $houseId, string $folder): DataResponse {
return $this->runAction(function () use ($houseId, $folder): DataResponse {
$uid = $this->requireUid();
$this->auth->requireMember($houseId, $uid);
$stored = $this->prefs->setImageFolder($uid, $houseId, $folder);
return new DataResponse(['folder' => $stored]);
});
}
/**
* Get photo sort preference for a house
*
* @param int $houseId House id.
*
* @return DataResponse<Http::STATUS_OK, array{sort: string, foldersFirst: bool}, array{}>
*
* 200: Sort preference returned
*/
#[ApiRoute(verb: 'GET', url: '/api/houses/{houseId}/prefs/photo-sort')]
#[NoAdminRequired]
public function getPhotoSort(int $houseId): DataResponse {
return $this->runAction(function () use ($houseId): DataResponse {
$uid = $this->requireUid();
$this->auth->requireMember($houseId, $uid);
return new DataResponse([
'sort' => $this->prefs->getPhotoSort($uid, $houseId),
'foldersFirst' => $this->prefs->getPhotoFoldersFirst($uid, $houseId),
]);
});
}
/**
* Set photo sort preference for a house
*
* @param int $houseId House id.
* @param string|null $sort Sort mode.
* @param bool|null $foldersFirst Whether folders appear first.
*
* @return DataResponse<Http::STATUS_OK, array{sort: string, foldersFirst: bool}, array{}>
*
* 200: Sort preference updated
*/
#[ApiRoute(verb: 'PUT', url: '/api/houses/{houseId}/prefs/photo-sort')]
#[NoAdminRequired]
public function setPhotoSort(int $houseId, ?string $sort = null, ?bool $foldersFirst = null): DataResponse {
return $this->runAction(function () use ($houseId, $sort, $foldersFirst): DataResponse {
$uid = $this->requireUid();
$this->auth->requireMember($houseId, $uid);
if ($sort !== null) {
$this->prefs->setPhotoSort($uid, $houseId, $sort);
}
if ($foldersFirst !== null) {
$this->prefs->setPhotoFoldersFirst($uid, $houseId, $foldersFirst);
}
return new DataResponse([
'sort' => $this->prefs->getPhotoSort($uid, $houseId),
'foldersFirst' => $this->prefs->getPhotoFoldersFirst($uid, $houseId),
]);
});
}
/**
* Get note sort preference for a house
*
* @param int $houseId House id.
*
* @return DataResponse<Http::STATUS_OK, array{sort: string}, array{}>
*
* 200: Sort preference returned
*/
#[ApiRoute(verb: 'GET', url: '/api/houses/{houseId}/prefs/note-sort')]
#[NoAdminRequired]
public function getNoteSort(int $houseId): DataResponse {
return $this->runAction(function () use ($houseId): DataResponse {
$uid = $this->requireUid();
$this->auth->requireMember($houseId, $uid);
return new DataResponse([
'sort' => $this->prefs->getNoteSort($uid, $houseId),
]);
});
}
/**
* Set note sort preference for a house
*
* @param int $houseId House id.
* @param string $sort Sort mode.
*
* @return DataResponse<Http::STATUS_OK, array{sort: string}, array{}>
*
* 200: Sort preference updated
*/
#[ApiRoute(verb: 'PUT', url: '/api/houses/{houseId}/prefs/note-sort')]
#[NoAdminRequired]
public function setNoteSort(int $houseId, string $sort): DataResponse {
return $this->runAction(function () use ($houseId, $sort): DataResponse {
$uid = $this->requireUid();
$this->auth->requireMember($houseId, $uid);
$stored = $this->prefs->setNoteSort($uid, $houseId, $sort);
return new DataResponse(['sort' => $stored]);
});
}
/**
* Get checklist item sort preference for a house
*
* @param int $houseId House id.
*
* @return DataResponse<Http::STATUS_OK, array{sort: string}, array{}>
*
* 200: Sort preference returned
*/
#[ApiRoute(verb: 'GET', url: '/api/houses/{houseId}/prefs/checklist-item-sort')]
#[NoAdminRequired]
public function getChecklistItemSort(int $houseId): DataResponse {
return $this->runAction(function () use ($houseId): DataResponse {
$uid = $this->requireUid();
$this->auth->requireMember($houseId, $uid);
return new DataResponse([
'sort' => $this->prefs->getChecklistItemSort($uid, $houseId),
]);
});
}
/**
* Set checklist item sort preference for a house
*
* @param int $houseId House id.
* @param string $sort Sort mode.
*
* @return DataResponse<Http::STATUS_OK, array{sort: string}, array{}>
*
* 200: Sort preference updated
*/
#[ApiRoute(verb: 'PUT', url: '/api/houses/{houseId}/prefs/checklist-item-sort')]
#[NoAdminRequired]
public function setChecklistItemSort(int $houseId, string $sort): DataResponse {
return $this->runAction(function () use ($houseId, $sort): DataResponse {
$uid = $this->requireUid();
$this->auth->requireMember($houseId, $uid);
$stored = $this->prefs->setChecklistItemSort($uid, $houseId, $sort);
return new DataResponse(['sort' => $stored]);
});
}
/**
* Get notification preferences for a house
*
* @param int $houseId House id.
*
* @return DataResponse<Http::STATUS_OK, PantryNotificationPrefs, array{}>
* @return DataResponse<Http::STATUS_OK, PantryHousePrefs, array{}>
*
* 200: Prefs returned
*/
#[ApiRoute(verb: 'GET', url: '/api/houses/{houseId}/prefs/notifications')]
#[ApiRoute(verb: 'GET', url: '/api/houses/{houseId}/prefs')]
#[NoAdminRequired]
public function getNotificationPrefs(int $houseId): DataResponse {
public function getHousePrefs(int $houseId): DataResponse {
return $this->runAction(function () use ($houseId): DataResponse {
$uid = $this->requireUid();
$this->auth->requireMember($houseId, $uid);
return new DataResponse($this->prefs->getNotificationPrefs($uid, $houseId));
return new DataResponse($this->prefs->getAllHousePrefs($uid, $houseId));
});
}
/**
* Update notification preferences for a house
* Update per-house preferences for the current user
*
* Only the fields present in the request body are updated; omitted fields
* are left unchanged.
*
* @param int $houseId House id.
* @param string|null $imageFolder Image upload folder path.
* @param string|null $photoSort Photo sort mode.
* @param bool|null $photoFoldersFirst Whether folders appear first in photo board.
* @param string|null $noteSort Note sort mode.
* @param string|null $checklistItemSort Checklist item sort mode.
* @param bool|null $notifyPhoto Photo upload notifications.
* @param bool|null $notifyNoteCreate Note creation notifications.
* @param bool|null $notifyNoteEdit Note edit notifications.
@@ -291,35 +128,44 @@ final class PrefsController extends OCSController {
* @param bool|null $notifyItemRecur Recurring item reappeared notifications.
* @param bool|null $notifyItemDone Item completed notifications.
*
* @return DataResponse<Http::STATUS_OK, PantryNotificationPrefs, array{}>
* @return DataResponse<Http::STATUS_OK, PantryHousePrefs, array{}>
*
* 200: Prefs updated
*/
#[ApiRoute(verb: 'PUT', url: '/api/houses/{houseId}/prefs/notifications')]
#[ApiRoute(verb: 'PUT', url: '/api/houses/{houseId}/prefs')]
#[NoAdminRequired]
public function setNotificationPrefs(int $houseId, ?bool $notifyPhoto = null, ?bool $notifyNoteCreate = null, ?bool $notifyNoteEdit = null, ?bool $notifyItemAdd = null, ?bool $notifyItemRecur = null, ?bool $notifyItemDone = null): DataResponse {
return $this->runAction(function () use ($houseId, $notifyPhoto, $notifyNoteCreate, $notifyNoteEdit, $notifyItemAdd, $notifyItemRecur, $notifyItemDone): DataResponse {
public function setHousePrefs(
int $houseId,
?string $imageFolder = null,
?string $photoSort = null,
?bool $photoFoldersFirst = null,
?string $noteSort = null,
?string $checklistItemSort = null,
?bool $notifyPhoto = null,
?bool $notifyNoteCreate = null,
?bool $notifyNoteEdit = null,
?bool $notifyItemAdd = null,
?bool $notifyItemRecur = null,
?bool $notifyItemDone = null,
): DataResponse {
return $this->runAction(function () use ($houseId, $imageFolder, $photoSort, $photoFoldersFirst, $noteSort, $checklistItemSort, $notifyPhoto, $notifyNoteCreate, $notifyNoteEdit, $notifyItemAdd, $notifyItemRecur, $notifyItemDone): DataResponse {
$uid = $this->requireUid();
$this->auth->requireMember($houseId, $uid);
if ($notifyPhoto !== null) {
$this->prefs->setNotificationPref($uid, $houseId, 'notify_photo', $notifyPhoto);
}
if ($notifyNoteCreate !== null) {
$this->prefs->setNotificationPref($uid, $houseId, 'notify_note_create', $notifyNoteCreate);
}
if ($notifyNoteEdit !== null) {
$this->prefs->setNotificationPref($uid, $houseId, 'notify_note_edit', $notifyNoteEdit);
}
if ($notifyItemAdd !== null) {
$this->prefs->setNotificationPref($uid, $houseId, 'notify_item_add', $notifyItemAdd);
}
if ($notifyItemRecur !== null) {
$this->prefs->setNotificationPref($uid, $houseId, 'notify_item_recur', $notifyItemRecur);
}
if ($notifyItemDone !== null) {
$this->prefs->setNotificationPref($uid, $houseId, 'notify_item_done', $notifyItemDone);
}
return new DataResponse($this->prefs->getNotificationPrefs($uid, $houseId));
$patch = array_filter([
'imageFolder' => $imageFolder,
'photoSort' => $photoSort,
'photoFoldersFirst' => $photoFoldersFirst,
'noteSort' => $noteSort,
'checklistItemSort' => $checklistItemSort,
'notifyPhoto' => $notifyPhoto,
'notifyNoteCreate' => $notifyNoteCreate,
'notifyNoteEdit' => $notifyNoteEdit,
'notifyItemAdd' => $notifyItemAdd,
'notifyItemRecur' => $notifyItemRecur,
'notifyItemDone' => $notifyItemDone,
], fn ($v) => $v !== null);
$this->prefs->setHousePrefs($uid, $houseId, $patch);
return new DataResponse($this->prefs->getAllHousePrefs($uid, $houseId));
});
}

View File

@@ -70,11 +70,17 @@ namespace OCA\Pantry;
*
* @psalm-type PantrySuccess = array{success: true}
*
* @psalm-type PantryLastHouse = array{houseId: int|null}
* @psalm-type PantryUserPrefs = array{
* lastHouseId: int|null,
* firstDayOfWeek: int,
* }
*
* @psalm-type PantryImageFolder = array{folder: string}
*
* @psalm-type PantryNotificationPrefs = array{
* @psalm-type PantryHousePrefs = array{
* imageFolder: string,
* photoSort: string,
* photoFoldersFirst: bool,
* noteSort: string,
* checklistItemSort: string,
* notifyPhoto: bool,
* notifyNoteCreate: bool,
* notifyNoteEdit: bool,

View File

@@ -9,6 +9,7 @@ namespace OCA\Pantry\Service;
use OCA\Pantry\AppInfo\Application;
use OCP\IConfig;
use OCP\IL10N;
class PrefsService {
private const KEY_LAST_HOUSE = 'last_house_id';
@@ -17,9 +18,18 @@ class PrefsService {
public function __construct(
private IConfig $config,
private IL10N $l,
) {
}
public function getFirstDayOfWeek(string $uid): int {
$value = $this->config->getUserValue($uid, 'core', 'first_day_of_week', '');
if ($value === '') {
return (int)$this->l->l('firstday', null);
}
return (int)$value;
}
public function getLastHouseId(string $uid): ?int {
$value = $this->config->getUserValue($uid, Application::APP_ID, self::KEY_LAST_HOUSE, '');
if ($value === '') {
@@ -52,6 +62,28 @@ class PrefsService {
return $normalized;
}
// ----- Unified user prefs -----
/**
* @return array<string, mixed>
*/
public function getAllUserPrefs(string $uid): array {
return [
'lastHouseId' => $this->getLastHouseId($uid),
'firstDayOfWeek' => $this->getFirstDayOfWeek($uid),
];
}
/**
* @param array<string, mixed> $patch
*/
public function setUserPrefs(string $uid, array $patch): void {
if (array_key_exists('lastHouseId', $patch)) {
$v = $patch['lastHouseId'];
$this->setLastHouseId($uid, is_int($v) ? $v : null);
}
}
// ----- Sort preferences -----
private const KEY_PHOTO_SORT = 'photo_sort';
@@ -164,6 +196,57 @@ class PrefsService {
];
}
// ----- Unified house prefs -----
/**
* @return array<string, mixed>
*/
public function getAllHousePrefs(string $uid, int $houseId): array {
return [
'imageFolder' => $this->getImageFolder($uid, $houseId),
'photoSort' => $this->getPhotoSort($uid, $houseId),
'photoFoldersFirst' => $this->getPhotoFoldersFirst($uid, $houseId),
'noteSort' => $this->getNoteSort($uid, $houseId),
'checklistItemSort' => $this->getChecklistItemSort($uid, $houseId),
...$this->getNotificationPrefs($uid, $houseId),
];
}
/**
* @param array<string, mixed> $patch
*/
public function setHousePrefs(string $uid, int $houseId, array $patch): void {
if (array_key_exists('imageFolder', $patch) && is_string($patch['imageFolder'])) {
$this->setImageFolder($uid, $houseId, $patch['imageFolder']);
}
if (array_key_exists('photoSort', $patch) && is_string($patch['photoSort'])) {
$this->setPhotoSort($uid, $houseId, $patch['photoSort']);
}
if (array_key_exists('photoFoldersFirst', $patch) && is_bool($patch['photoFoldersFirst'])) {
$this->setPhotoFoldersFirst($uid, $houseId, $patch['photoFoldersFirst']);
}
if (array_key_exists('noteSort', $patch) && is_string($patch['noteSort'])) {
$this->setNoteSort($uid, $houseId, $patch['noteSort']);
}
if (array_key_exists('checklistItemSort', $patch) && is_string($patch['checklistItemSort'])) {
$this->setChecklistItemSort($uid, $houseId, $patch['checklistItemSort']);
}
// Notification prefs
$notifKeys = [
'notifyPhoto' => 'notify_photo',
'notifyNoteCreate' => 'notify_note_create',
'notifyNoteEdit' => 'notify_note_edit',
'notifyItemAdd' => 'notify_item_add',
'notifyItemRecur' => 'notify_item_recur',
'notifyItemDone' => 'notify_item_done',
];
foreach ($notifKeys as $camel => $dbKey) {
if (array_key_exists($camel, $patch) && is_bool($patch[$camel])) {
$this->setNotificationPref($uid, $houseId, $dbKey, $patch[$camel]);
}
}
}
private function normalizeFolder(string $folder): string {
$trimmed = trim($folder);
if ($trimmed === '') {

File diff suppressed because it is too large Load Diff

View File

@@ -1,77 +1,44 @@
import { ocs } from '@/axios'
// ----- User-level prefs (not per-house) -----
export interface UserPrefs {
lastHouseId: number | null
/** 0 = Sunday, 1 = Monday, …, 6 = Saturday. Read-only from server. */
firstDayOfWeek: number
}
export async function getUserPrefs(): Promise<UserPrefs> {
const resp = await ocs.get<UserPrefs>('/prefs')
return resp.data ?? { lastHouseId: null, firstDayOfWeek: 1 }
}
export async function setUserPrefs(patch: Partial<UserPrefs>): Promise<UserPrefs> {
const resp = await ocs.put<UserPrefs>('/prefs', patch)
return resp.data ?? { lastHouseId: null, firstDayOfWeek: 1 }
}
// Convenience wrappers (used widely, keep the simple API)
export async function getLastHouse(): Promise<number | null> {
const resp = await ocs.get<{ houseId: number | null }>('/prefs/last-house')
return resp.data?.houseId ?? null
const prefs = await getUserPrefs()
return prefs.lastHouseId
}
export async function setLastHouse(houseId: number | null): Promise<void> {
await ocs.put('/prefs/last-house', { houseId })
await setUserPrefs({ lastHouseId: houseId })
}
export async function getImageFolder(houseId: number): Promise<string> {
const resp = await ocs.get<{ folder: string }>(`/houses/${houseId}/prefs/image-folder`)
return resp.data?.folder ?? '/Pantry'
}
export async function setImageFolder(houseId: number, folder: string): Promise<string> {
const resp = await ocs.put<{ folder: string }>(`/houses/${houseId}/prefs/image-folder`, {
folder,
})
return resp.data?.folder ?? folder
}
// ----- Per-house prefs -----
export type PhotoSort = 'custom' | 'newest' | 'oldest' | 'description_asc' | 'description_desc'
export type NoteSort = 'custom' | 'newest' | 'oldest' | 'title_asc' | 'title_desc'
export type ChecklistItemSort = 'custom' | 'newest' | 'oldest' | 'name_asc' | 'name_desc'
export interface PhotoSortPrefs {
sort: PhotoSort
foldersFirst: boolean
}
export async function getPhotoSort(houseId: number): Promise<PhotoSortPrefs> {
const resp = await ocs.get<PhotoSortPrefs>(`/houses/${houseId}/prefs/photo-sort`)
return resp.data ?? { sort: 'custom', foldersFirst: true }
}
export async function setPhotoSort(
houseId: number,
prefs: Partial<PhotoSortPrefs>,
): Promise<PhotoSortPrefs> {
const resp = await ocs.put<PhotoSortPrefs>(`/houses/${houseId}/prefs/photo-sort`, prefs)
return resp.data ?? { sort: 'custom', foldersFirst: true }
}
export async function getNoteSort(houseId: number): Promise<{ sort: NoteSort }> {
const resp = await ocs.get<{ sort: NoteSort }>(`/houses/${houseId}/prefs/note-sort`)
return resp.data ?? { sort: 'custom' }
}
export async function setNoteSort(houseId: number, sort: NoteSort): Promise<{ sort: NoteSort }> {
const resp = await ocs.put<{ sort: NoteSort }>(`/houses/${houseId}/prefs/note-sort`, { sort })
return resp.data ?? { sort }
}
export type ChecklistItemSort = 'custom' | 'newest' | 'oldest' | 'name_asc' | 'name_desc'
export async function getChecklistItemSort(houseId: number): Promise<{ sort: ChecklistItemSort }> {
const resp = await ocs.get<{ sort: ChecklistItemSort }>(
`/houses/${houseId}/prefs/checklist-item-sort`,
)
return resp.data ?? { sort: 'custom' }
}
export async function setChecklistItemSort(
houseId: number,
sort: ChecklistItemSort,
): Promise<{ sort: ChecklistItemSort }> {
const resp = await ocs.put<{ sort: ChecklistItemSort }>(
`/houses/${houseId}/prefs/checklist-item-sort`,
{ sort },
)
return resp.data ?? { sort }
}
export interface NotificationPrefs {
notifyPhoto: boolean
notifyNoteCreate: boolean
@@ -81,33 +48,115 @@ export interface NotificationPrefs {
notifyItemDone: boolean
}
export interface HousePrefs extends NotificationPrefs {
imageFolder: string
photoSort: PhotoSort
photoFoldersFirst: boolean
noteSort: NoteSort
checklistItemSort: ChecklistItemSort
}
const housePrefsDefaults: HousePrefs = {
imageFolder: '/Pantry',
photoSort: 'custom',
photoFoldersFirst: true,
noteSort: 'custom',
checklistItemSort: 'custom',
notifyPhoto: true,
notifyNoteCreate: true,
notifyNoteEdit: true,
notifyItemAdd: true,
notifyItemRecur: true,
notifyItemDone: true,
}
export async function getHousePrefs(houseId: number): Promise<HousePrefs> {
const resp = await ocs.get<HousePrefs>(`/houses/${houseId}/prefs`)
return { ...housePrefsDefaults, ...resp.data }
}
export async function setHousePrefs(
houseId: number,
patch: Partial<HousePrefs>,
): Promise<HousePrefs> {
const resp = await ocs.put<HousePrefs>(`/houses/${houseId}/prefs`, patch)
return { ...housePrefsDefaults, ...resp.data }
}
// ----- Convenience wrappers for individual prefs -----
export async function getPhotoSort(houseId: number): Promise<PhotoSortPrefs> {
const p = await getHousePrefs(houseId)
return { sort: p.photoSort, foldersFirst: p.photoFoldersFirst }
}
export async function setPhotoSort(
houseId: number,
prefs: Partial<PhotoSortPrefs>,
): Promise<PhotoSortPrefs> {
const patch: Partial<HousePrefs> = {}
if (prefs.sort !== undefined) patch.photoSort = prefs.sort
if (prefs.foldersFirst !== undefined) patch.photoFoldersFirst = prefs.foldersFirst
const p = await setHousePrefs(houseId, patch)
return { sort: p.photoSort, foldersFirst: p.photoFoldersFirst }
}
export async function getNoteSort(houseId: number): Promise<{ sort: NoteSort }> {
const p = await getHousePrefs(houseId)
return { sort: p.noteSort }
}
export async function setNoteSort(houseId: number, sort: NoteSort): Promise<{ sort: NoteSort }> {
const p = await setHousePrefs(houseId, { noteSort: sort })
return { sort: p.noteSort }
}
export async function getChecklistItemSort(houseId: number): Promise<{ sort: ChecklistItemSort }> {
const p = await getHousePrefs(houseId)
return { sort: p.checklistItemSort }
}
export async function setChecklistItemSort(
houseId: number,
sort: ChecklistItemSort,
): Promise<{ sort: ChecklistItemSort }> {
const p = await setHousePrefs(houseId, { checklistItemSort: sort })
return { sort: p.checklistItemSort }
}
export async function getImageFolder(houseId: number): Promise<string> {
const p = await getHousePrefs(houseId)
return p.imageFolder
}
export async function setImageFolder(houseId: number, folder: string): Promise<string> {
const p = await setHousePrefs(houseId, { imageFolder: folder })
return p.imageFolder
}
export async function getNotificationPrefs(houseId: number): Promise<NotificationPrefs> {
const resp = await ocs.get<NotificationPrefs>(`/houses/${houseId}/prefs/notifications`)
return (
resp.data ?? {
notifyPhoto: true,
notifyNoteCreate: true,
notifyNoteEdit: true,
notifyItemAdd: true,
notifyItemRecur: true,
notifyItemDone: true,
}
)
const p = await getHousePrefs(houseId)
return {
notifyPhoto: p.notifyPhoto,
notifyNoteCreate: p.notifyNoteCreate,
notifyNoteEdit: p.notifyNoteEdit,
notifyItemAdd: p.notifyItemAdd,
notifyItemRecur: p.notifyItemRecur,
notifyItemDone: p.notifyItemDone,
}
}
export async function setNotificationPrefs(
houseId: number,
prefs: Partial<NotificationPrefs>,
): Promise<NotificationPrefs> {
const resp = await ocs.put<NotificationPrefs>(`/houses/${houseId}/prefs/notifications`, prefs)
return (
resp.data ?? {
notifyPhoto: true,
notifyNoteCreate: true,
notifyNoteEdit: true,
notifyItemAdd: true,
notifyItemRecur: true,
notifyItemDone: true,
}
)
const p = await setHousePrefs(houseId, prefs)
return {
notifyPhoto: p.notifyPhoto,
notifyNoteCreate: p.notifyNoteCreate,
notifyNoteEdit: p.notifyNoteEdit,
notifyItemAdd: p.notifyItemAdd,
notifyItemRecur: p.notifyItemRecur,
notifyItemDone: p.notifyItemDone,
}
}

View File

@@ -10,17 +10,22 @@ namespace OCA\Pantry\Tests\Unit\Service;
use OCA\Pantry\AppInfo\Application;
use OCA\Pantry\Service\PrefsService;
use OCP\IConfig;
use OCP\IL10N;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
class PrefsServiceTest extends TestCase {
/** @var IConfig&MockObject */
private IConfig $config;
/** @var IL10N&MockObject */
private IL10N $l;
private PrefsService $svc;
protected function setUp(): void {
$this->config = $this->createMock(IConfig::class);
$this->svc = new PrefsService($this->config);
$this->l = $this->createMock(IL10N::class);
$this->l->method('l')->willReturn('1'); // Monday fallback
$this->svc = new PrefsService($this->config, $this->l);
}
// ----- Notification preferences -----