Compare commits

...

3 commits

Author SHA1 Message Date
shenlong
e1739ac4fc
fix(mobile): allow editing asset dates in the future (#5522)
Co-authored-by: shalong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2023-12-06 20:04:03 -06:00
martin
8736c77f7a
fix(web): align all edit buttons and not correctly rounded buttons on detail-panel (#5524)
* fix: align all pencils

* fix: format
2023-12-06 20:03:28 -06:00
James Keane
338a028185
fix(server): awaitsendFile (#5515)
Fixes the intermittent EPIPE errors that myself and others are seeing.

By explicitly returning a promise we ensure the caller correctly waits until the `sendFile` is complete before potentially closing or cleaning the socket. This is the most likely bug that would cause EPIPE errors.

Fix was confirmed on a live system -- would benefit from a unit test
though.
2023-12-06 20:51:51 -05:00
4 changed files with 26 additions and 14 deletions

View file

@ -86,11 +86,14 @@ class _DateTimePicker extends HookWidget {
final timeZones = useMemoized(() => getAllTimeZones(), const []); final timeZones = useMemoized(() => getAllTimeZones(), const []);
void pickDate() async { void pickDate() async {
final now = DateTime.now();
// Handles cases where the date from the asset is far off in the future
final initialDate = date.value.isAfter(now) ? now : date.value;
final newDate = await showDatePicker( final newDate = await showDatePicker(
context: context, context: context,
initialDate: date.value, initialDate: initialDate,
firstDate: DateTime(1800), firstDate: DateTime(1800),
lastDate: DateTime.now(), lastDate: now,
); );
if (newDate == null) { if (newDate == null) {
return; return;

View file

@ -336,14 +336,18 @@ export class AssetService {
res.set('Cache-Control', 'private, max-age=86400, no-transform'); res.set('Cache-Control', 'private, max-age=86400, no-transform');
res.header('Content-Type', mimeTypes.lookup(filepath)); res.header('Content-Type', mimeTypes.lookup(filepath));
res.sendFile(filepath, options, (error: Error) => { return new Promise((resolve, reject) => {
if (!error) { res.sendFile(filepath, options, (error: Error) => {
return; if (!error) {
} resolve();
return;
}
if (error.message !== 'Request aborted') { if (error.message !== 'Request aborted') {
this.logger.error(`Unable to send file: ${error.name}`, error.stack); this.logger.error(`Unable to send file: ${error.name}`, error.stack);
} }
reject(error);
});
}); });
} }

View file

@ -205,12 +205,13 @@
<section class="px-4 py-4 text-sm"> <section class="px-4 py-4 text-sm">
<div class="flex h-10 w-full items-center justify-between"> <div class="flex h-10 w-full items-center justify-between">
<h2>PEOPLE</h2> <h2>PEOPLE</h2>
<div class="flex gap-2"> <div class="flex gap-2 items-center">
{#if people.some((person) => person.isHidden)} {#if people.some((person) => person.isHidden)}
<CircleIconButton <CircleIconButton
title="Show hidden people" title="Show hidden people"
icon={showingHiddenPeople ? mdiEyeOff : mdiEye} icon={showingHiddenPeople ? mdiEyeOff : mdiEye}
padding="1" padding="1"
buttonSize="32"
on:click={() => (showingHiddenPeople = !showingHiddenPeople)} on:click={() => (showingHiddenPeople = !showingHiddenPeople)}
/> />
{/if} {/if}
@ -219,6 +220,7 @@
icon={mdiPencil} icon={mdiPencil}
padding="1" padding="1"
size="20" size="20"
buttonSize="32"
on:click={() => (showEditFaces = true)} on:click={() => (showEditFaces = true)}
/> />
</div> </div>
@ -337,7 +339,7 @@
</div> </div>
{#if isOwner} {#if isOwner}
<button class="focus:outline-none"> <button class="focus:outline-none p-1">
<Icon path={mdiPencil} size="20" /> <Icon path={mdiPencil} size="20" />
</button> </button>
{/if} {/if}
@ -349,7 +351,7 @@
<Icon path={mdiCalendar} size="24" /> <Icon path={mdiCalendar} size="24" />
</div> </div>
</div> </div>
<button class="focus:outline-none"> <button class="focus:outline-none p-1">
<Icon path={mdiPencil} size="20" /> <Icon path={mdiPencil} size="20" />
</button> </button>
</div> </div>
@ -507,7 +509,7 @@
</div> </div>
{:else if !asset.exifInfo?.city && !asset.isReadOnly && $user && asset.ownerId === $user.id} {:else if !asset.exifInfo?.city && !asset.isReadOnly && $user && asset.ownerId === $user.id}
<div <div
class="flex justify-between place-items-start gap-4 py-4 rounded-lg pr-2 hover:dark:text-immich-dark-primary hover:text-immich-primary" class="flex justify-between place-items-start gap-4 py-4 rounded-lg hover:dark:text-immich-dark-primary hover:text-immich-primary"
on:click={() => (isShowChangeLocation = true)} on:click={() => (isShowChangeLocation = true)}
on:keydown={(event) => event.key === 'Enter' && (isShowChangeLocation = true)} on:keydown={(event) => event.key === 'Enter' && (isShowChangeLocation = true)}
tabindex="0" tabindex="0"
@ -521,7 +523,7 @@
<p>Add a location</p> <p>Add a location</p>
</div> </div>
<div class="focus:outline-none"> <div class="focus:outline-none p-1">
<Icon path={mdiPencil} size="20" /> <Icon path={mdiPencil} size="20" />
</div> </div>
</div> </div>

View file

@ -11,10 +11,13 @@
export let forceDark = false; export let forceDark = false;
export let hideMobile = false; export let hideMobile = false;
export let iconColor = 'currentColor'; export let iconColor = 'currentColor';
export let buttonSize: string | undefined = undefined;
</script> </script>
<button <button
{title} {title}
style:width={buttonSize ? buttonSize + 'px' : ''}
style:height={buttonSize ? buttonSize + 'px' : ''}
style:background-color={backgroundColor} style:background-color={backgroundColor}
style:--immich-icon-button-hover-color={hoverColor} style:--immich-icon-button-hover-color={hoverColor}
class:dark:text-immich-dark-fg={!forceDark} class:dark:text-immich-dark-fg={!forceDark}