language files combined, settings fixed, "new" badge integrated
This commit is contained in:
@@ -2,8 +2,13 @@
|
||||
<div class="home">
|
||||
<div class="main-content">
|
||||
<div class="gallery-container" @touchstart="handleTouchStart" @touchend="handleTouchEnd">
|
||||
<h1 class="text-2xl font-bold text-center my-4">Style Gallery</h1>
|
||||
<GalleryGrid :images="paginatedImages" @imageTapped="showContextMenu" />
|
||||
<h1 class="text-2xl font-bold text-center my-4">{{ props.galleryHeading }}</h1>
|
||||
<div class="absolute top-4 right-4">
|
||||
<button @click="toggleTheme" class="theme-toggle-button">
|
||||
{{ currentTheme === 'light' ? __('api.dark_mode') : __('api.light_mode') }}
|
||||
</button>
|
||||
</div>
|
||||
<GalleryGrid :images="paginatedImages" @imageTapped="showContextMenu" :translations="props.translations" />
|
||||
<Navigation
|
||||
:currentPage="currentPage"
|
||||
:totalPages="totalPages"
|
||||
@@ -17,18 +22,10 @@
|
||||
v-if="currentOverlayComponent === 'contextMenu'"
|
||||
:position="contextMenuPosition"
|
||||
:image="selectedImage"
|
||||
@close="currentOverlayComponent = null"
|
||||
@close="currentOverlayComponent = null; selectedImage = null"
|
||||
@print="printImage"
|
||||
@changeStyle="showStyleSelector"
|
||||
/>
|
||||
|
||||
<StyleSelector
|
||||
v-if="currentOverlayComponent === 'styleSelector'"
|
||||
:position="contextMenuPosition"
|
||||
:image_id="selectedImage.image_id"
|
||||
@styleSelected="applyStyle"
|
||||
@back="goBackToContextMenu"
|
||||
@close="currentOverlayComponent = null"
|
||||
/>
|
||||
|
||||
<div v-if="errorMessage" class="fixed bottom-4 right-4 bg-red-500 text-white p-4 rounded-lg shadow-lg z-50">
|
||||
@@ -46,38 +43,15 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import Navigation from '../Components/Navigation.vue';
|
||||
import GalleryGrid from '../Components/GalleryGrid.vue';
|
||||
import ImageContextMenu from '../Components/ImageContextMenu.vue';
|
||||
import StyleSelector from '../Components/StyleSelector.vue';
|
||||
import StyledImageDisplay from '../Components/StyledImageDisplay.vue'; // Import the new component
|
||||
import LoadingSpinner from '../Components/LoadingSpinner.vue'; // Import the new component
|
||||
import axios from 'axios';
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue';
|
||||
import { defineProps } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
galleryHeading: String,
|
||||
translations: Object,
|
||||
});
|
||||
|
||||
const images = ref([]);
|
||||
const imagesPerPage = 12;
|
||||
const currentPage = ref(1);
|
||||
const currentOverlayComponent = ref(null); // null, 'contextMenu', 'styleSelector', 'styledImageDisplay'
|
||||
const contextMenuPosition = ref({ x: 0, y: 0 });
|
||||
const selectedImage = ref(null);
|
||||
const styledImage = ref(null); // To store the newly styled image
|
||||
const errorMessage = ref(null); // New ref for error messages
|
||||
const isLoading = ref(false); // New ref for loading state
|
||||
let fetchInterval = null;
|
||||
let touchStartX = 0;
|
||||
let touchEndX = 0;
|
||||
|
||||
|
||||
const totalPages = computed(() => {
|
||||
return Math.ceil(images.value.length / imagesPerPage);
|
||||
});
|
||||
|
||||
const paginatedImages = computed(() => {
|
||||
const start = (currentPage.value - 1) * imagesPerPage;
|
||||
const end = start + imagesPerPage;
|
||||
return images.value.slice(start, end);
|
||||
});
|
||||
|
||||
const fetchImages = () => {
|
||||
axios.get('/api/images')
|
||||
@@ -90,6 +64,50 @@ const fetchImages = () => {
|
||||
});
|
||||
};
|
||||
|
||||
import Navigation from '../Components/Navigation.vue';
|
||||
import GalleryGrid from '../Components/GalleryGrid.vue';
|
||||
import ImageContextMenu from '../Components/ImageContextMenu.vue';
|
||||
import StyleSelector from '../Components/StyleSelector.vue';
|
||||
import StyledImageDisplay from '../Components/StyledImageDisplay.vue'; // Import the new component
|
||||
import LoadingSpinner from '../Components/LoadingSpinner.vue'; // Import the new component
|
||||
import axios from 'axios';
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue';
|
||||
|
||||
const imagesPerPage = 12;
|
||||
const currentPage = ref(1);
|
||||
const currentOverlayComponent = ref(null); // null, 'contextMenu', 'styleSelector', 'styledImageDisplay'
|
||||
const contextMenuPosition = ref({ x: 0, y: 0 });
|
||||
const selectedImage = ref(null);
|
||||
const styledImage = ref(null); // To store the newly styled image
|
||||
const errorMessage = ref(null); // New ref for error messages
|
||||
const isLoading = ref(false); // New ref for loading state
|
||||
const currentTheme = ref('light'); // New ref for current theme
|
||||
|
||||
let touchStartX = 0;
|
||||
let touchEndX = 0;
|
||||
|
||||
const applyTheme = (theme) => {
|
||||
document.documentElement.classList.remove('light', 'dark');
|
||||
document.documentElement.classList.add(theme);
|
||||
localStorage.setItem('theme', theme);
|
||||
currentTheme.value = theme;
|
||||
};
|
||||
|
||||
const toggleTheme = () => {
|
||||
const newTheme = currentTheme.value === 'light' ? 'dark' : 'light';
|
||||
applyTheme(newTheme);
|
||||
};
|
||||
|
||||
const totalPages = computed(() => {
|
||||
return Math.ceil(images.value.length / imagesPerPage);
|
||||
});
|
||||
|
||||
const paginatedImages = computed(() => {
|
||||
const start = (currentPage.value - 1) * imagesPerPage;
|
||||
const end = start + imagesPerPage;
|
||||
return images.value.slice(start, end);
|
||||
});
|
||||
|
||||
const showError = (message) => {
|
||||
errorMessage.value = message;
|
||||
setTimeout(() => {
|
||||
@@ -142,8 +160,6 @@ const applyStyle = (style, imageId) => {
|
||||
const keepStyledImage = (imageToKeep) => {
|
||||
console.log('Keeping styled image:', imageToKeep);
|
||||
// Implement API call to mark image as kept/permanent if needed
|
||||
// For now, just refresh the image list to show the new image
|
||||
fetchImages();
|
||||
currentOverlayComponent.value = null; // Close the display
|
||||
};
|
||||
|
||||
@@ -186,6 +202,16 @@ const handleSwipeGesture = () => {
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// Apply theme from localStorage on mount
|
||||
const savedTheme = localStorage.getItem('theme');
|
||||
if (savedTheme) {
|
||||
applyTheme(savedTheme);
|
||||
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
applyTheme('dark');
|
||||
} else {
|
||||
applyTheme('light');
|
||||
}
|
||||
|
||||
fetchImages();
|
||||
fetchInterval = setInterval(fetchImages, 5000);
|
||||
});
|
||||
@@ -216,4 +242,35 @@ onUnmounted(() => {
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.theme-toggle-button {
|
||||
margin-top: 10px;
|
||||
padding: 8px 15px;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.theme-toggle-button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.image-visibility-toggle-button {
|
||||
margin-top: 10px;
|
||||
padding: 8px 15px;
|
||||
background-color: #28a745;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 0.9em;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.image-visibility-toggle-button:hover {
|
||||
background-color: #218838;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user