mirror of
https://github.com/TeamPiped/Piped.git
synced 2026-03-29 11:56:58 +00:00
implement fixes for review
This commit is contained in:
@@ -3,12 +3,12 @@
|
||||
<div class="flex min-w-[50vw] flex-col">
|
||||
<div class="h-[70vh] overflow-y-scroll pr-4">
|
||||
<span v-t="'actions.add_to_group'" class="mb-3 inline-block w-max text-2xl" />
|
||||
<div v-for="(group, index) in channelGroups" :key="group.groupName" class="px-1">
|
||||
<div v-for="group in channelGroups" :key="group.groupName" class="px-1">
|
||||
<div class="flex items-center justify-between">
|
||||
<span>{{ group.groupName }}</span>
|
||||
<UiCheckbox
|
||||
:model-value="group.channels.includes(channelId)"
|
||||
@update:model-value="onCheckedChange(index, group)"
|
||||
@update:model-value="onCheckedChange(group)"
|
||||
/>
|
||||
</div>
|
||||
<hr class="h-1 w-full" />
|
||||
@@ -56,9 +56,12 @@ onMounted(() => {
|
||||
loadChannelGroups();
|
||||
});
|
||||
|
||||
function onCheckedChange(index, group) {
|
||||
function onCheckedChange(group) {
|
||||
if (group.channels.includes(props.channelId)) {
|
||||
group.channels.splice(index, 1);
|
||||
const channelIndex = group.channels.indexOf(props.channelId);
|
||||
if (channelIndex !== -1) {
|
||||
group.channels.splice(channelIndex, 1);
|
||||
}
|
||||
} else {
|
||||
group.channels.push(props.channelId);
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
<a
|
||||
:href="getRssUrl"
|
||||
class="inline-block w-auto cursor-pointer rounded-sm bg-gray-300 py-2 text-gray-600 hover:bg-gray-500 hover:text-white max-md:px-2 md:px-4 dark:bg-dark-400 dark:text-gray-400 dark:hover:bg-dark-300"
|
||||
:aria-label="$t('actions.rss_feed')"
|
||||
>
|
||||
<i-fa6-solid-rss />
|
||||
</a>
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
<a
|
||||
class="mr-1 inline-block w-auto cursor-pointer rounded-sm bg-gray-300 py-2 text-gray-600 hover:bg-gray-500 hover:text-white focus:shadow-red-400 focus:outline-2 focus:outline-red-500 max-md:px-2 md:px-4 dark:bg-dark-400 dark:text-gray-400 dark:hover:bg-dark-300"
|
||||
:href="getRssUrl"
|
||||
:aria-label="$t('actions.playlist_rss_feed')"
|
||||
>
|
||||
<i-fa6-solid-rss />
|
||||
</a>
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
<div class="flex flex-wrap justify-between">
|
||||
<div class="flex gap-1">
|
||||
<!-- import json/csv -->
|
||||
<button
|
||||
<router-link
|
||||
v-t="'actions.import_from_json_csv'"
|
||||
to="/import"
|
||||
class="inline-block w-auto cursor-pointer rounded-sm bg-gray-300 py-2 text-gray-600 hover:bg-gray-500 hover:text-white focus:shadow-red-400 focus:outline-2 focus:outline-red-500 max-md:px-2 md:px-4 dark:bg-dark-400 dark:text-gray-400 dark:hover:bg-dark-300"
|
||||
>
|
||||
<router-link v-t="'actions.import_from_json_csv'" to="/import" />
|
||||
</button>
|
||||
/>
|
||||
<!-- export to json -->
|
||||
<button
|
||||
v-t="'actions.export_to_json'"
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
<button
|
||||
:type="type"
|
||||
:class="[
|
||||
'inline-block w-auto cursor-pointer rounded-sm py-2 text-gray-600 hover:bg-gray-500 hover:text-white focus:shadow-red-400 focus:outline-2 focus:outline-red-500 max-md:px-2 md:px-4 dark:text-gray-400 dark:hover:bg-dark-300',
|
||||
variant === 'primary' ? 'bg-gray-300 dark:bg-dark-400' : 'bg-gray-300 dark:bg-dark-400',
|
||||
'inline-block w-auto cursor-pointer rounded-sm py-2 text-gray-600 hover:bg-gray-500 hover:text-white focus:shadow-sm focus:shadow-red-400 focus:outline-2 focus:outline-red-500 max-md:px-2 md:px-4 dark:text-gray-400 dark:hover:bg-dark-300',
|
||||
variant === 'primary'
|
||||
? 'bg-gray-300 dark:bg-dark-400'
|
||||
: 'border border-gray-500 bg-transparent dark:border-gray-400',
|
||||
customClass,
|
||||
]"
|
||||
v-bind="$attrs"
|
||||
|
||||
@@ -1,25 +1,7 @@
|
||||
<template>
|
||||
<CheckboxRoot
|
||||
v-if="hasModelValue"
|
||||
:id="id"
|
||||
:model-value="modelValue"
|
||||
:value="value"
|
||||
:disabled="disabled"
|
||||
:class="[
|
||||
'inline-flex size-4 shrink-0 items-center justify-center rounded-sm border border-gray-500 bg-gray-300 text-white outline-none focus:shadow-red-400 focus:outline-2 focus:outline-red-500 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:border-red-500 data-[state=checked]:bg-red-500 dark:border-gray-400 dark:bg-dark-400 dark:data-[state=checked]:border-red-400 dark:data-[state=checked]:bg-red-400',
|
||||
customClass,
|
||||
]"
|
||||
@update:model-value="handleUpdate"
|
||||
>
|
||||
<CheckboxIndicator class="inline-flex items-center justify-center text-current">
|
||||
<i-fa6-solid-check class="size-3" />
|
||||
</CheckboxIndicator>
|
||||
</CheckboxRoot>
|
||||
|
||||
<CheckboxRoot
|
||||
v-else
|
||||
:id="id"
|
||||
:value="value"
|
||||
:disabled="disabled"
|
||||
:class="[
|
||||
'inline-flex size-4 shrink-0 items-center justify-center rounded-sm border border-gray-500 bg-gray-300 text-white outline-none focus:shadow-red-400 focus:outline-2 focus:outline-red-500 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:border-red-500 data-[state=checked]:bg-red-500 dark:border-gray-400 dark:bg-dark-400 dark:data-[state=checked]:border-red-400 dark:data-[state=checked]:bg-red-400',
|
||||
@@ -34,25 +16,20 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
import { CheckboxRoot, CheckboxIndicator } from "reka-ui";
|
||||
|
||||
defineOptions({
|
||||
name: "UiCheckbox",
|
||||
});
|
||||
|
||||
const props = defineProps({
|
||||
defineProps({
|
||||
id: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
},
|
||||
modelValue: {
|
||||
type: [Boolean, String, Number, Array],
|
||||
default: undefined,
|
||||
},
|
||||
value: {
|
||||
type: [Boolean, String, Number],
|
||||
default: true,
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
@@ -66,10 +43,9 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "change"]);
|
||||
|
||||
const hasModelValue = computed(() => props.modelValue !== undefined);
|
||||
|
||||
function handleUpdate(value) {
|
||||
emit("update:modelValue", value);
|
||||
emit("change", value);
|
||||
const nextValue = value === true;
|
||||
emit("update:modelValue", nextValue);
|
||||
emit("change", nextValue);
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<button
|
||||
type="button"
|
||||
class="absolute right-3 size-4 cursor-pointer rounded-full bg-gray-300 text-center text-[10px] text-black opacity-50 hover:opacity-70 dark:bg-gray-400"
|
||||
:aria-label="$t('actions.clear', { count: 0 }) || 'Clear'"
|
||||
:aria-label="$t('actions.clear')"
|
||||
@click="$emit('clear')"
|
||||
>
|
||||
⨉
|
||||
@@ -10,8 +10,9 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
defineEmits(["clear"]);
|
||||
|
||||
import { useI18n } from "vue-i18n";
|
||||
const { t: $t } = useI18n();
|
||||
</script>
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
<button
|
||||
type="button"
|
||||
class="ml-2 inline-block w-auto cursor-pointer rounded-sm bg-gray-300 py-2 text-gray-600 hover:bg-gray-500 hover:text-white focus:shadow-red-400 focus:outline-2 focus:outline-red-500 max-md:px-2 md:px-4 dark:bg-dark-400 dark:text-gray-400 dark:hover:bg-dark-300"
|
||||
:aria-label="modelValue ? $t('actions.hide_password') : $t('actions.show_password')"
|
||||
:aria-pressed="modelValue"
|
||||
@click="$emit('update:modelValue', !modelValue)"
|
||||
>
|
||||
<i-fa6-solid-eye v-if="!modelValue" />
|
||||
@@ -10,6 +12,8 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
defineProps({
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
@@ -18,4 +22,6 @@ defineProps({
|
||||
});
|
||||
|
||||
defineEmits(["update:modelValue"]);
|
||||
|
||||
const { t: $t } = useI18n();
|
||||
</script>
|
||||
|
||||
@@ -32,12 +32,19 @@ function createPreferenceRefForValue(key, valueForTypeInference) {
|
||||
}
|
||||
|
||||
export function usePreferenceString(key, defaultVal) {
|
||||
return getOrCreatePreferenceRef(key, () =>
|
||||
const preferenceRef = getOrCreatePreferenceRef(key, () =>
|
||||
useLocalStorage(key, defaultVal ?? null, {
|
||||
serializer: StorageSerializers.any,
|
||||
writeDefaults: false,
|
||||
}),
|
||||
);
|
||||
|
||||
const queryValue = getQueryPreference(key);
|
||||
if (queryValue !== null && preferenceRef.value !== queryValue) {
|
||||
preferenceRef.value = queryValue;
|
||||
}
|
||||
|
||||
return preferenceRef;
|
||||
}
|
||||
|
||||
export function usePreferenceBoolean(key, defaultVal = false) {
|
||||
@@ -104,14 +111,20 @@ export function getPreferenceBoolean(key, defaultVal) {
|
||||
}
|
||||
|
||||
export function getPreferenceString(key, defaultVal) {
|
||||
const queryValue = getQueryPreference(key);
|
||||
if (queryValue !== null) return queryValue;
|
||||
|
||||
if (testLocalStorage()) {
|
||||
const value = usePreferenceString(key, defaultVal).value;
|
||||
const preferenceRef = usePreferenceString(key, defaultVal);
|
||||
const queryValue = getQueryPreference(key);
|
||||
if (queryValue !== null && preferenceRef.value !== queryValue) {
|
||||
preferenceRef.value = queryValue;
|
||||
}
|
||||
|
||||
const value = preferenceRef.value;
|
||||
return value ?? defaultVal;
|
||||
}
|
||||
|
||||
const queryValue = getQueryPreference(key);
|
||||
if (queryValue !== null) return queryValue;
|
||||
|
||||
return defaultVal;
|
||||
}
|
||||
|
||||
@@ -133,7 +146,13 @@ export function getPreferenceNumber(key, defaultVal) {
|
||||
|
||||
export function getPreferenceJSON(key, defaultVal) {
|
||||
const queryValue = getQueryPreference(key);
|
||||
if (queryValue !== null) return JSON.parse(queryValue);
|
||||
if (queryValue !== null) {
|
||||
try {
|
||||
return JSON.parse(queryValue);
|
||||
} catch {
|
||||
return defaultVal;
|
||||
}
|
||||
}
|
||||
|
||||
if (testLocalStorage()) {
|
||||
const value = usePreferenceJSON(key, defaultVal).value;
|
||||
|
||||
@@ -91,6 +91,7 @@
|
||||
"search": "Search (Ctrl+K)",
|
||||
"filter": "Filter",
|
||||
"loading": "Loading…",
|
||||
"clear": "Clear",
|
||||
"clear_history": "Clear History",
|
||||
"hide_replies": "Hide Replies",
|
||||
"load_more_replies": "Load more Replies",
|
||||
@@ -172,7 +173,11 @@
|
||||
"export": "Export",
|
||||
"never": "Never",
|
||||
"playlists_only": "Playlists only",
|
||||
"always": "Always"
|
||||
"always": "Always",
|
||||
"show_password": "Show password",
|
||||
"hide_password": "Hide password",
|
||||
"rss_feed": "RSS feed",
|
||||
"playlist_rss_feed": "Playlist RSS feed"
|
||||
},
|
||||
"comment": {
|
||||
"pinned_by": "Pinned by {author}",
|
||||
|
||||
Reference in New Issue
Block a user