Compare commits
2 Commits
7d7cd25040
...
4f9807cfe7
| Author | SHA1 | Date | |
|---|---|---|---|
| 4f9807cfe7 | |||
| f89548b363 |
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {computed, onMounted, ref, watch, nextTick} from 'vue'
|
import {computed, nextTick, onMounted, ref, watch} from 'vue'
|
||||||
import {useRoute, useRouter} from 'vue-router'
|
import {useRoute, useRouter} from 'vue-router'
|
||||||
import {dataService} from '../services/dataService'
|
import {dataService} from '../services/dataService'
|
||||||
import {aiService} from '../services/aiService'
|
import {aiService} from '../services/aiService'
|
||||||
@@ -7,7 +7,6 @@ import Button from 'primevue/button'
|
|||||||
import Skeleton from 'primevue/skeleton'
|
import Skeleton from 'primevue/skeleton'
|
||||||
import Tag from 'primevue/tag'
|
import Tag from 'primevue/tag'
|
||||||
import Dialog from 'primevue/dialog'
|
import Dialog from 'primevue/dialog'
|
||||||
import Textarea from 'primevue/textarea'
|
|
||||||
import Checkbox from 'primevue/checkbox'
|
import Checkbox from 'primevue/checkbox'
|
||||||
import ProgressBar from 'primevue/progressbar'
|
import ProgressBar from 'primevue/progressbar'
|
||||||
import Message from 'primevue/message'
|
import Message from 'primevue/message'
|
||||||
@@ -19,8 +18,6 @@ import Tab from 'primevue/tab'
|
|||||||
import TabPanels from 'primevue/tabpanels'
|
import TabPanels from 'primevue/tabpanels'
|
||||||
import TabPanel from 'primevue/tabpanel'
|
import TabPanel from 'primevue/tabpanel'
|
||||||
import Paginator from 'primevue/paginator'
|
import Paginator from 'primevue/paginator'
|
||||||
import MultiSelect from 'primevue/multiselect'
|
|
||||||
import Dropdown from 'primevue/dropdown'
|
|
||||||
|
|
||||||
import GenerationPreviewModal from '../components/GenerationPreviewModal.vue'
|
import GenerationPreviewModal from '../components/GenerationPreviewModal.vue'
|
||||||
|
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ const modalAssets = ref([])
|
|||||||
const isModalLoading = ref(false)
|
const isModalLoading = ref(false)
|
||||||
const tempSelectedAssets = ref([])
|
const tempSelectedAssets = ref([])
|
||||||
const quality = ref({ key: 'TWOK', value: '2K' })
|
const quality = ref({ key: 'TWOK', value: '2K' })
|
||||||
const aspectRatio = ref({ key: "NINESIXTEEN", value: "9:16" })
|
const aspectRatio = ref('NINESIXTEEN') // Default to Video (9:16)
|
||||||
const generationCount = ref(1)
|
const generationCount = ref(1)
|
||||||
const sendToTelegram = ref(false)
|
const sendToTelegram = ref(false)
|
||||||
const telegramId = ref('')
|
const telegramId = ref('')
|
||||||
@@ -164,7 +164,7 @@ const previousPrompt = ref('')
|
|||||||
let _savedEnvironmentId = null
|
let _savedEnvironmentId = null
|
||||||
|
|
||||||
// NSFW Toggle
|
// NSFW Toggle
|
||||||
const showNsfwGlobal = ref(localStorage.getItem('show_nsfw_global') === 'true')
|
const showNsfwGlobal = ref(false)
|
||||||
|
|
||||||
watch(showNsfwGlobal, (val) => {
|
watch(showNsfwGlobal, (val) => {
|
||||||
localStorage.setItem('show_nsfw_global', val)
|
localStorage.setItem('show_nsfw_global', val)
|
||||||
@@ -218,18 +218,6 @@ const qualityOptions = ref([
|
|||||||
{ key: 'TWOK', value: '2K' },
|
{ key: 'TWOK', value: '2K' },
|
||||||
{ key: 'FOURK', value: '4K' }
|
{ key: 'FOURK', value: '4K' }
|
||||||
])
|
])
|
||||||
const aspectRatioOptions = ref([
|
|
||||||
{ key: "ONEONE", value: "1:1" },
|
|
||||||
{ key: "TWOTHREE", value: "2:3" },
|
|
||||||
{ key: "THREETWO", value: "3:2" },
|
|
||||||
{ key: "THREEFOUR", value: "3:4" },
|
|
||||||
{ key: "FOURTHREE", value: "4:3" },
|
|
||||||
{ key: "FOURFIVE", value: "4:5" },
|
|
||||||
{ key: "FIVEFOUR", value: "5:4" },
|
|
||||||
{ key: "NINESIXTEEN", value: "9:16" },
|
|
||||||
{ key: "SIXTEENNINE", value: "16:9" },
|
|
||||||
{ key: "TWENTYONENINE", value: "21:9" }
|
|
||||||
])
|
|
||||||
|
|
||||||
// --- Persistence ---
|
// --- Persistence ---
|
||||||
const STORAGE_KEY = 'flexible_gen_settings'
|
const STORAGE_KEY = 'flexible_gen_settings'
|
||||||
@@ -267,7 +255,14 @@ const restoreSettings = () => {
|
|||||||
// We need characters and assets loaded to fully restore objects
|
// We need characters and assets loaded to fully restore objects
|
||||||
// For now, we'll store IDs and restore in loadData
|
// For now, we'll store IDs and restore in loadData
|
||||||
if (settings.quality) quality.value = settings.quality
|
if (settings.quality) quality.value = settings.quality
|
||||||
if (settings.aspectRatio) aspectRatio.value = settings.aspectRatio
|
if (settings.aspectRatio) {
|
||||||
|
// Handle legacy object format if present
|
||||||
|
if (typeof settings.aspectRatio === 'object' && settings.aspectRatio.key) {
|
||||||
|
aspectRatio.value = settings.aspectRatio.key
|
||||||
|
} else {
|
||||||
|
aspectRatio.value = settings.aspectRatio
|
||||||
|
}
|
||||||
|
}
|
||||||
sendToTelegram.value = settings.sendToTelegram || false
|
sendToTelegram.value = settings.sendToTelegram || false
|
||||||
telegramId.value = settings.telegramId || localStorage.getItem('telegram_id') || ''
|
telegramId.value = settings.telegramId || localStorage.getItem('telegram_id') || ''
|
||||||
if (telegramId.value) isTelegramIdSaved.value = true
|
if (telegramId.value) isTelegramIdSaved.value = true
|
||||||
@@ -429,7 +424,7 @@ const handleGenerate = async () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const payload = {
|
const payload = {
|
||||||
aspect_ratio: aspectRatio.value.key,
|
aspect_ratio: aspectRatio.value, // Now a string
|
||||||
quality: quality.value.key,
|
quality: quality.value.key,
|
||||||
prompt: prompt.value,
|
prompt: prompt.value,
|
||||||
assets_list: selectedAssets.value.map(a => a.id),
|
assets_list: selectedAssets.value.map(a => a.id),
|
||||||
@@ -560,6 +555,10 @@ const loadMoreHistory = async () => {
|
|||||||
|
|
||||||
// --- Initial Load ---
|
// --- Initial Load ---
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
// Reset NSFW on page load
|
||||||
|
showNsfwGlobal.value = false
|
||||||
|
localStorage.removeItem('show_nsfw_global')
|
||||||
|
|
||||||
loadData().then(() => {
|
loadData().then(() => {
|
||||||
// slight delay to allow DOM render
|
// slight delay to allow DOM render
|
||||||
setTimeout(setupInfiniteScroll, 500)
|
setTimeout(setupInfiniteScroll, 500)
|
||||||
@@ -902,6 +901,13 @@ const confirmAddToAlbum = async () => {
|
|||||||
class="!w-7 !h-7 !p-0"
|
class="!w-7 !h-7 !p-0"
|
||||||
:class="onlyLiked ? '!text-pink-500 !bg-pink-500/10' : '!text-slate-400 hover:!bg-white/10'"
|
:class="onlyLiked ? '!text-pink-500 !bg-pink-500/10' : '!text-slate-400 hover:!bg-white/10'"
|
||||||
v-tooltip.bottom="onlyLiked ? 'Show all' : 'Show liked only'" />
|
v-tooltip.bottom="onlyLiked ? 'Show all' : 'Show liked only'" />
|
||||||
|
|
||||||
|
<Button :icon="showNsfwGlobal ? 'pi pi-eye' : 'pi pi-eye-slash'"
|
||||||
|
@click="showNsfwGlobal = !showNsfwGlobal" rounded text
|
||||||
|
class="!w-7 !h-7 !p-0"
|
||||||
|
:class="showNsfwGlobal ? '!text-red-400 !bg-red-500/10' : '!text-slate-400 hover:!bg-white/10'"
|
||||||
|
v-tooltip.bottom="showNsfwGlobal ? 'Hide NSFW' : 'Show NSFW'" />
|
||||||
|
|
||||||
<Button icon="pi pi-refresh" @click="refreshHistory" rounded text
|
<Button icon="pi pi-refresh" @click="refreshHistory" rounded text
|
||||||
class="!text-slate-400 hover:!bg-white/10 !w-7 !h-7 !p-0 md:hidden" />
|
class="!text-slate-400 hover:!bg-white/10 !w-7 !h-7 !p-0 md:hidden" />
|
||||||
<Button :icon="isSelectMode ? 'pi pi-times' : 'pi pi-check-square'" @click="toggleSelectMode"
|
<Button :icon="isSelectMode ? 'pi pi-times' : 'pi pi-check-square'" @click="toggleSelectMode"
|
||||||
@@ -1159,11 +1165,22 @@ const confirmAddToAlbum = async () => {
|
|||||||
:pt="{ input: { class: '!text-white' }, trigger: { class: '!text-slate-400' }, panel: { class: '!bg-slate-800 !border-white/10' }, item: { class: '!text-slate-300 hover:!bg-white/10 hover:!text-white' } }" />
|
:pt="{ input: { class: '!text-white' }, trigger: { class: '!text-slate-400' }, panel: { class: '!bg-slate-800 !border-white/10' }, item: { class: '!text-slate-300 hover:!bg-white/10 hover:!text-white' } }" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<label class="text-xs font-bold text-slate-400 uppercase tracking-wider">Aspect
|
<label class="text-xs font-bold text-slate-400 uppercase tracking-wider">Format</label>
|
||||||
Ratio</label>
|
<div class="flex items-center">
|
||||||
<Dropdown v-model="aspectRatio" :options="aspectRatioOptions" optionLabel="value"
|
<div class="flex-1 flex bg-slate-800 rounded-xl border border-white/10 overflow-hidden">
|
||||||
class="w-full !bg-slate-800 !border-white/10 !text-white !rounded-xl"
|
<button @click="aspectRatio = 'THREEFOUR'"
|
||||||
:pt="{ input: { class: '!text-white' }, trigger: { class: '!text-slate-400' }, panel: { class: '!bg-slate-800 !border-white/10' }, item: { class: '!text-slate-300 hover:!bg-white/10 hover:!text-white' } }" />
|
class="flex-1 py-2 text-sm font-bold transition-all flex items-center justify-center gap-1"
|
||||||
|
:class="aspectRatio === 'THREEFOUR' ? 'bg-violet-600 text-white' : 'text-slate-400 hover:text-white hover:bg-white/5'">
|
||||||
|
<i class="pi pi-image"></i> Photo
|
||||||
|
</button>
|
||||||
|
<div class="w-px bg-white/10"></div>
|
||||||
|
<button @click="aspectRatio = 'NINESIXTEEN'"
|
||||||
|
class="flex-1 py-2 text-sm font-bold transition-all flex items-center justify-center gap-1"
|
||||||
|
:class="aspectRatio === 'NINESIXTEEN' ? 'bg-violet-600 text-white' : 'text-slate-400 hover:text-white hover:bg-white/5'">
|
||||||
|
<i class="pi pi-video"></i> Video
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -1193,14 +1210,6 @@ const confirmAddToAlbum = async () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- NSFW Toggle -->
|
|
||||||
<div class="flex flex-col gap-2 bg-slate-800/50 p-3 rounded-xl border border-white/5">
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<label class="text-xs text-slate-300 cursor-pointer">Show NSFW</label>
|
|
||||||
<InputSwitch v-model="showNsfwGlobal" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-auto">
|
<div class="mt-auto">
|
||||||
<Button :label="isSubmitting ? 'Starting...' : 'Generate'"
|
<Button :label="isSubmitting ? 'Starting...' : 'Generate'"
|
||||||
:icon="isSubmitting ? 'pi pi-spin pi-spinner' : 'pi pi-sparkles'"
|
:icon="isSubmitting ? 'pi pi-spin pi-spinner' : 'pi pi-sparkles'"
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ const showAssetPicker = ref(false) // Deprecated, using isAssetPickerVisible
|
|||||||
// --- Load saved settings from localStorage ---
|
// --- Load saved settings from localStorage ---
|
||||||
const SETTINGS_KEY = 'idea-gen-settings'
|
const SETTINGS_KEY = 'idea-gen-settings'
|
||||||
const quality = ref({ key: 'TWOK', value: '2K' })
|
const quality = ref({ key: 'TWOK', value: '2K' })
|
||||||
const aspectRatio = ref({ key: 'NINESIXTEEN', value: '9:16' })
|
const aspectRatio = ref('NINESIXTEEN') // Default to Video (9:16)
|
||||||
const imageCount = ref(1)
|
const imageCount = ref(1)
|
||||||
const sendToTelegram = ref(false)
|
const sendToTelegram = ref(false)
|
||||||
const telegramId = ref('')
|
const telegramId = ref('')
|
||||||
@@ -160,7 +160,14 @@ const restoreSettings = () => {
|
|||||||
const s = JSON.parse(stored)
|
const s = JSON.parse(stored)
|
||||||
if (s.prompt) prompt.value = s.prompt
|
if (s.prompt) prompt.value = s.prompt
|
||||||
if (s.quality) quality.value = s.quality
|
if (s.quality) quality.value = s.quality
|
||||||
if (s.aspectRatio) aspectRatio.value = s.aspectRatio
|
if (s.aspectRatio) {
|
||||||
|
// Handle legacy object format if present
|
||||||
|
if (typeof s.aspectRatio === 'object' && s.aspectRatio.key) {
|
||||||
|
aspectRatio.value = s.aspectRatio.key
|
||||||
|
} else {
|
||||||
|
aspectRatio.value = s.aspectRatio
|
||||||
|
}
|
||||||
|
}
|
||||||
if (s.imageCount) imageCount.value = Math.min(s.imageCount, 4)
|
if (s.imageCount) imageCount.value = Math.min(s.imageCount, 4)
|
||||||
if (s.selectedModel) selectedModel.value = s.selectedModel
|
if (s.selectedModel) selectedModel.value = s.selectedModel
|
||||||
sendToTelegram.value = s.sendToTelegram || false
|
sendToTelegram.value = s.sendToTelegram || false
|
||||||
@@ -200,18 +207,6 @@ const qualityOptions = ref([
|
|||||||
{ key: 'TWOK', value: '2K' },
|
{ key: 'TWOK', value: '2K' },
|
||||||
{ key: 'FOURK', value: '4K' }
|
{ key: 'FOURK', value: '4K' }
|
||||||
])
|
])
|
||||||
const aspectRatioOptions = ref([
|
|
||||||
{ key: "ONEONE", value: "1:1" },
|
|
||||||
{ key: "TWOTHREE", value: "2:3" },
|
|
||||||
{ key: "THREETWO", value: "3:2" },
|
|
||||||
{ key: "THREEFOUR", value: "3:4" },
|
|
||||||
{ key: "FOURTHREE", value: "4:3" },
|
|
||||||
{ key: "FOURFIVE", value: "4:5" },
|
|
||||||
{ key: "FIVEFOUR", value: "5:4" },
|
|
||||||
{ key: "NINESIXTEEN", value: "9:16" },
|
|
||||||
{ key: "SIXTEENNINE", value: "16:9" },
|
|
||||||
{ key: "TWENTYONENINE", value: "21:9" }
|
|
||||||
])
|
|
||||||
|
|
||||||
// Removed duplicate characters ref
|
// Removed duplicate characters ref
|
||||||
const loadingGenerations = ref(false) // Added this ref based on usage in fetchGenerations
|
const loadingGenerations = ref(false) // Added this ref based on usage in fetchGenerations
|
||||||
@@ -312,7 +307,7 @@ const handleGenerate = async () => {
|
|||||||
// Construct Payload
|
// Construct Payload
|
||||||
const payload = {
|
const payload = {
|
||||||
prompt: prompt.value,
|
prompt: prompt.value,
|
||||||
aspect_ratio: aspectRatio.value.key,
|
aspect_ratio: aspectRatio.value, // Now a string
|
||||||
quality: quality.value.key,
|
quality: quality.value.key,
|
||||||
assets_list: selectedAssets.value.map(a => a.id),
|
assets_list: selectedAssets.value.map(a => a.id),
|
||||||
linked_character_id: selectedCharacter.value?.id || selectedCharacter.value?._id || null,
|
linked_character_id: selectedCharacter.value?.id || selectedCharacter.value?._id || null,
|
||||||
@@ -1373,7 +1368,7 @@ watch(viewMode, (v) => {
|
|||||||
class="flex-shrink-0 flex items-center gap-2 px-2 py-1.5 rounded-lg border-2 transition-all cursor-pointer group bg-slate-800/40"
|
class="flex-shrink-0 flex items-center gap-2 px-2 py-1.5 rounded-lg border-2 transition-all cursor-pointer group bg-slate-800/40"
|
||||||
:class="[
|
:class="[
|
||||||
(selectedEnvironment?.id === (env.id || env._id) || selectedEnvironment?._id === (env.id || env._id))
|
(selectedEnvironment?.id === (env.id || env._id) || selectedEnvironment?._id === (env.id || env._id))
|
||||||
? 'border-violet-500 bg-violet-500/10 shadow-[0_0_15px_rgba(124,58,237,0.15)]'
|
? 'border-violet-500 bg-violet-500/10 shadow-[0_0_15px_rgba(124,58,237,0.1)]'
|
||||||
: 'border-white/5 hover:border-white/20'
|
: 'border-white/5 hover:border-white/20'
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
@@ -1411,10 +1406,22 @@ watch(viewMode, (v) => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<label
|
<label
|
||||||
class="text-[10px] font-bold text-slate-400 uppercase tracking-wider">Ratio</label>
|
class="text-[10px] font-bold text-slate-400 uppercase tracking-wider">Format</label>
|
||||||
<Dropdown v-model="aspectRatio" :options="aspectRatioOptions" optionLabel="value"
|
<div class="flex items-center">
|
||||||
class="w-full !bg-slate-800 !border-white/10 !text-white !rounded-xl"
|
<div class="flex-1 flex bg-slate-800 rounded-lg border border-white/10 overflow-hidden">
|
||||||
:pt="{ input: { class: '!text-white' }, trigger: { class: '!text-slate-400' }, panel: { class: '!bg-slate-800 !border-white/10' }, item: { class: '!text-slate-300 hover:!bg-white/10 hover:!text-white' } }" />
|
<button @click="aspectRatio = 'THREEFOUR'"
|
||||||
|
class="flex-1 py-1 text-xs font-bold transition-all flex items-center justify-center gap-1"
|
||||||
|
:class="aspectRatio === 'THREEFOUR' ? 'bg-violet-600 text-white' : 'text-slate-400 hover:text-white hover:bg-white/5'">
|
||||||
|
<i class="pi pi-image"></i> Photo
|
||||||
|
</button>
|
||||||
|
<div class="w-px bg-white/10"></div>
|
||||||
|
<button @click="aspectRatio = 'NINESIXTEEN'"
|
||||||
|
class="flex-1 py-1 text-xs font-bold transition-all flex items-center justify-center gap-1"
|
||||||
|
:class="aspectRatio === 'NINESIXTEEN' ? 'bg-violet-600 text-white' : 'text-slate-400 hover:text-white hover:bg-white/5'">
|
||||||
|
<i class="pi pi-video"></i> Video
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user