Task #613: replace per-app hide toggles with single Dock visibility switch
The per-app hidden feature shipped in #609 was rejected — user wanted one toggle that hides/shows the entire bottom AppDock bar, leaving Home apps untouched. Removed: - lib/db/src/schema/user-hidden-apps.ts (and index.ts export); table dropped via `pnpm --filter @workspace/db run push` - GET /me/apps and PUT /me/apps/:appId/hidden routes - getHiddenAppIdsForUser + getVisibleNonHiddenAppsForUser helpers - MyApp + UpdateMyAppHiddenBody OpenAPI schemas - MyAppsBody settings UI + related i18n keys - Regenerated api-client-react + api-zod from the trimmed spec - Reverted GET /apps back to getVisibleAppsForUser Added: - artifacts/tx-os/src/hooks/use-dock-visible.ts — localStorage-backed preference with a custom window event for in-tab sync and the native `storage` event for cross-tab sync. Default = true. - DockBody in settings-panel: single ToggleRow under a new "App dock" section ("settingsPanel.section.dock" / "settingsPanel.dock.show") - AppDock now returns null when the preference is off and clears `--app-dock-height` so page padding doesn't stay reserved. Code review: PASS (architect). No remaining references to the removed infra. Typecheck shows only pre-existing errors in executive-meetings.ts and push.ts unrelated to this change. Follow-up: publish to Gitea + redeploy on Mac (proposed as a follow-up task).
This commit is contained in:
@@ -763,15 +763,6 @@ export interface AppSettings {
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
export type MyApp = App & {
|
||||
/** True when the current user has hidden this app from their Home/Dock. */
|
||||
hidden: boolean;
|
||||
};
|
||||
|
||||
export interface UpdateMyAppHiddenBody {
|
||||
hidden: boolean;
|
||||
}
|
||||
|
||||
export interface UpdateMyAppOrderBody {
|
||||
/** App IDs in the desired display order */
|
||||
order: number[];
|
||||
|
||||
@@ -80,7 +80,6 @@ import type {
|
||||
ListReceivedNotesParams,
|
||||
ListUsersParams,
|
||||
LoginBody,
|
||||
MyApp,
|
||||
MyNote,
|
||||
NoteFolder,
|
||||
NoteReply,
|
||||
@@ -119,7 +118,6 @@ import type {
|
||||
UpdateClockStyleBody,
|
||||
UpdateGroupBody,
|
||||
UpdateLanguageBody,
|
||||
UpdateMyAppHiddenBody,
|
||||
UpdateMyAppOrderBody,
|
||||
UpdateNoteFolderBody,
|
||||
UpdateNoteFolderParams,
|
||||
@@ -2254,172 +2252,6 @@ export const useUpdateMyAppOrder = <
|
||||
return useMutation(getUpdateMyAppOrderMutationOptions(options));
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns every globally active app (regardless of the per-user hidden
|
||||
flag), each with a `hidden` boolean indicating whether the current
|
||||
user has hidden it from their own Home/Dock via PUT /me/apps/{appId}/hidden.
|
||||
Used by the per-user Settings panel; the Home and Dock continue to use
|
||||
GET /apps which already filters out hidden apps server-side.
|
||||
|
||||
* @summary List apps for the current user with their per-user hidden state
|
||||
*/
|
||||
export const getListMyAppsUrl = () => {
|
||||
return `/api/me/apps`;
|
||||
};
|
||||
|
||||
export const listMyApps = async (options?: RequestInit): Promise<MyApp[]> => {
|
||||
return customFetch<MyApp[]>(getListMyAppsUrl(), {
|
||||
...options,
|
||||
method: "GET",
|
||||
});
|
||||
};
|
||||
|
||||
export const getListMyAppsQueryKey = () => {
|
||||
return [`/api/me/apps`] as const;
|
||||
};
|
||||
|
||||
export const getListMyAppsQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof listMyApps>>,
|
||||
TError = ErrorType<unknown>,
|
||||
>(options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listMyApps>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
request?: SecondParameter<typeof customFetch>;
|
||||
}) => {
|
||||
const { query: queryOptions, request: requestOptions } = options ?? {};
|
||||
|
||||
const queryKey = queryOptions?.queryKey ?? getListMyAppsQueryKey();
|
||||
|
||||
const queryFn: QueryFunction<Awaited<ReturnType<typeof listMyApps>>> = ({
|
||||
signal,
|
||||
}) => listMyApps({ signal, ...requestOptions });
|
||||
|
||||
return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listMyApps>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type ListMyAppsQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof listMyApps>>
|
||||
>;
|
||||
export type ListMyAppsQueryError = ErrorType<unknown>;
|
||||
|
||||
/**
|
||||
* @summary List apps for the current user with their per-user hidden state
|
||||
*/
|
||||
|
||||
export function useListMyApps<
|
||||
TData = Awaited<ReturnType<typeof listMyApps>>,
|
||||
TError = ErrorType<unknown>,
|
||||
>(options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listMyApps>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
request?: SecondParameter<typeof customFetch>;
|
||||
}): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getListMyAppsQueryOptions(options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
return { ...query, queryKey: queryOptions.queryKey };
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Hide or show an app for the current user
|
||||
*/
|
||||
export const getUpdateMyAppHiddenUrl = (appId: number) => {
|
||||
return `/api/me/apps/${appId}/hidden`;
|
||||
};
|
||||
|
||||
export const updateMyAppHidden = async (
|
||||
appId: number,
|
||||
updateMyAppHiddenBody: UpdateMyAppHiddenBody,
|
||||
options?: RequestInit,
|
||||
): Promise<MyApp> => {
|
||||
return customFetch<MyApp>(getUpdateMyAppHiddenUrl(appId), {
|
||||
...options,
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json", ...options?.headers },
|
||||
body: JSON.stringify(updateMyAppHiddenBody),
|
||||
});
|
||||
};
|
||||
|
||||
export const getUpdateMyAppHiddenMutationOptions = <
|
||||
TError = ErrorType<ErrorResponse>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateMyAppHidden>>,
|
||||
TError,
|
||||
{ appId: number; data: BodyType<UpdateMyAppHiddenBody> },
|
||||
TContext
|
||||
>;
|
||||
request?: SecondParameter<typeof customFetch>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateMyAppHidden>>,
|
||||
TError,
|
||||
{ appId: number; data: BodyType<UpdateMyAppHiddenBody> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ["updateMyAppHidden"];
|
||||
const { mutation: mutationOptions, request: requestOptions } = options
|
||||
? options.mutation &&
|
||||
"mutationKey" in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey }, request: undefined };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof updateMyAppHidden>>,
|
||||
{ appId: number; data: BodyType<UpdateMyAppHiddenBody> }
|
||||
> = (props) => {
|
||||
const { appId, data } = props ?? {};
|
||||
|
||||
return updateMyAppHidden(appId, data, requestOptions);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type UpdateMyAppHiddenMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof updateMyAppHidden>>
|
||||
>;
|
||||
export type UpdateMyAppHiddenMutationBody = BodyType<UpdateMyAppHiddenBody>;
|
||||
export type UpdateMyAppHiddenMutationError = ErrorType<ErrorResponse>;
|
||||
|
||||
/**
|
||||
* @summary Hide or show an app for the current user
|
||||
*/
|
||||
export const useUpdateMyAppHidden = <
|
||||
TError = ErrorType<ErrorResponse>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateMyAppHidden>>,
|
||||
TError,
|
||||
{ appId: number; data: BodyType<UpdateMyAppHiddenBody> },
|
||||
TContext
|
||||
>;
|
||||
request?: SecondParameter<typeof customFetch>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof updateMyAppHidden>>,
|
||||
TError,
|
||||
{ appId: number; data: BodyType<UpdateMyAppHiddenBody> },
|
||||
TContext
|
||||
> => {
|
||||
return useMutation(getUpdateMyAppHiddenMutationOptions(options));
|
||||
};
|
||||
|
||||
/**
|
||||
* @summary Get application settings (public)
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user