feat: share list
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
- [x] handle errors
|
||||
- [x] list per URL
|
||||
- [x] home screen
|
||||
- [ ] share link
|
||||
- [x] share link
|
||||
- [ ] fill new list with "fill todo" item
|
||||
- [x] lang in cookies
|
||||
- [ ] simple view
|
||||
|
||||
@@ -68,10 +68,13 @@
|
||||
"task_create_error": "Could not create task",
|
||||
"task_cloned": "Task cloned",
|
||||
"task_deleted": "Task deleted",
|
||||
"task_delete_error": "Could not delete task"
|
||||
"task_delete_error": "Could not delete task",
|
||||
"share_clipboard": "Link copied to clipboard",
|
||||
"share_error": "Could not share link"
|
||||
},
|
||||
"not_found": "Looks like there's nothing here...",
|
||||
"not_found_button": "Go back to familiar territory",
|
||||
"home": "A shareable task list with auto resetting items.<br/>Create your list below.",
|
||||
"home_button": "Let's go !"
|
||||
"home_button": "Let's go !",
|
||||
"share_button": "Share my list"
|
||||
}
|
||||
|
||||
@@ -68,10 +68,13 @@
|
||||
"task_create_error": "Impossible de créer la tâche",
|
||||
"task_cloned": "Tâche clonée",
|
||||
"task_deleted": "Tâche supprimée",
|
||||
"task_delete_error": "Impossible de supprimer la tâche"
|
||||
"task_delete_error": "Impossible de supprimer la tâche",
|
||||
"share_clipboard": "Lien copié dans le presse-papier",
|
||||
"share_error": "Impossible de partager le lien"
|
||||
},
|
||||
"not_found": "On dirait qu'il n'y a rien ici...",
|
||||
"not_found_button": "Retour en terrain connu",
|
||||
"home": "Une liste de tâches avec réinitialisation automatique des éléments.<br/>Créez ta liste ci-dessous.",
|
||||
"home_button": "C'est parti !"
|
||||
"home_button": "C'est parti !",
|
||||
"share_button": "Partager ma liste"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
export async function shareLink(
|
||||
title: string,
|
||||
text: string,
|
||||
url: string,
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
if (navigator.canShare()) {
|
||||
await navigator.share({ title, text, url });
|
||||
return true;
|
||||
}
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
await navigator.clipboard.writeText(url);
|
||||
return false;
|
||||
}
|
||||
@@ -44,9 +44,9 @@ onBeforeRouteUpdate(updateTitle);
|
||||
<dices-icon />
|
||||
</button>
|
||||
</div>
|
||||
<div class="w-full px-4">
|
||||
<div class="w-full">
|
||||
<router-link
|
||||
class="btn btn-lg"
|
||||
class="btn btn-lg px-4"
|
||||
:class="listNameInput.trim().length === 0 ? 'btn-disabled' : ''"
|
||||
:to="`/${listNameInput.trim()}`"
|
||||
>
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
CircleCheckBigIcon,
|
||||
CheckCheckIcon,
|
||||
SearchIcon,
|
||||
Share2Icon
|
||||
} from "@lucide/vue";
|
||||
const TaskItem = defineAsyncComponent(
|
||||
() => import("@/components/TaskItem.vue"),
|
||||
@@ -19,6 +20,7 @@ import { booleanCookieRef, enumCookieRef } from "@/lib/cookies";
|
||||
import { useAlertStore } from "@/stores/alerts";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { onBeforeRouteUpdate, useRoute } from "vue-router";
|
||||
import { shareLink } from "@/lib/share";
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
@@ -125,6 +127,18 @@ function onChangeSortReverse() {
|
||||
reSortTasks();
|
||||
}
|
||||
|
||||
function onShare() {
|
||||
shareLink(`Tout Doux - ${list.value ?? ''}`, '', `${document.location.href.split('?')[0] ?? ''}?lang=${i18n.locale.value}`)
|
||||
.then((viaShare) => {
|
||||
if (!viaShare) {
|
||||
alertSuccess(i18n.t("alerts.share_clipboard"));
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
alertError(i18n.t("alerts.share_error"))
|
||||
});
|
||||
}
|
||||
|
||||
function updateTitle() {
|
||||
if (list.value !== null) {
|
||||
document.title = `Tout Doux - ${list.value} (${completedCount.value.toFixed(0)}/${taskCount.value.toFixed(0)})`
|
||||
@@ -227,6 +241,11 @@ onBeforeRouteUpdate((to) => {
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-sm px-4" @click="onShare">
|
||||
<share-2-icon class="inline" :size="16" /> {{ $t('share_button') }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="collapse collapse-arrow font-light text-sm">
|
||||
<input id="options-dropdown" type="checkbox" />
|
||||
<div class="collapse-title">
|
||||
|
||||
@@ -15,7 +15,7 @@ onBeforeRouteUpdate(updateTitle);
|
||||
<div class="italic text-xl font-extralight mb-4">
|
||||
<circle-question-mark-icon class="inline" /> {{ $t('not_found') }}
|
||||
</div>
|
||||
<div class="w-full px-4">
|
||||
<router-link to="/" class="btn mb-4">{{ $t('not_found_button') }}</router-link>
|
||||
<div class="w-full">
|
||||
<router-link to="/" class="btn mb-4 px-4">{{ $t('not_found_button') }}</router-link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user