mirror of
https://github.com/mue/mue.git
synced 2026-07-22 08:17:28 +02:00
Add new localization strings for quote packs and update caching logic for authors
- Added "Installed Quote Packs" and "Get More" strings to multiple language files. - Updated the author caching mechanism in wikidataAuthorFetcher.js to limit the number of cached entries to 50 and prune old entries when the limit is exceeded. - Enhanced the occupation extraction logic to return the highest-ranked occupation based on Wikidata rank.
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
import variables from 'config/variables';
|
||||
import { memo, useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { MdSource, MdOutlineAutoAwesome } from 'react-icons/md';
|
||||
import { toast } from 'react-toastify';
|
||||
import EventBus from 'utils/eventbus';
|
||||
import { clearQueuesOnSettingChange } from 'utils/queueOperations';
|
||||
import { uninstall } from 'utils/marketplace';
|
||||
import { updateHash } from 'utils/deepLinking';
|
||||
|
||||
import { Header } from 'components/Layout/Settings';
|
||||
import { Dropdown } from 'components/Form/Settings';
|
||||
@@ -33,6 +36,18 @@ const BackgroundOptions = memo(({ currentSubSection, onSubSectionChange, section
|
||||
);
|
||||
const [marketplaceEnabled] = useState(localStorage.getItem('photo_packs'));
|
||||
|
||||
// Helper function to get installed photo packs
|
||||
const getInstalledPhotoPacks = () => {
|
||||
try {
|
||||
const installed = JSON.parse(localStorage.getItem('installed')) || [];
|
||||
return installed.filter((item) => item.type === 'photos');
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const [installedPhotoPacks, setInstalledPhotoPacks] = useState(getInstalledPhotoPacks());
|
||||
|
||||
// Auto-show source section for types without effects/display settings
|
||||
const shouldShowSourceByDefault = ['colour', 'random_colour', 'random_gradient'].includes(
|
||||
backgroundType,
|
||||
@@ -106,6 +121,56 @@ const BackgroundOptions = memo(({ currentSubSection, onSubSectionChange, section
|
||||
};
|
||||
}, [getBackgroundCategories]);
|
||||
|
||||
// Listen for installed addons changes
|
||||
useEffect(() => {
|
||||
const handleInstalledAddonsChanged = () => {
|
||||
setInstalledPhotoPacks(getInstalledPhotoPacks());
|
||||
// Update backgroundType if it changed (e.g., when all packs are uninstalled)
|
||||
const currentType = localStorage.getItem('backgroundType') || 'api';
|
||||
if (currentType !== backgroundType) {
|
||||
setBackgroundType(currentType);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('installedAddonsChanged', handleInstalledAddonsChanged);
|
||||
return () => window.removeEventListener('installedAddonsChanged', handleInstalledAddonsChanged);
|
||||
}, [backgroundType]);
|
||||
|
||||
// Handle photo pack uninstall
|
||||
const handlePhotoPackUninstall = (type, name) => {
|
||||
uninstall(type, name);
|
||||
toast(variables.getMessage('toasts.uninstalled'));
|
||||
variables.stats.postEvent('marketplace-item', `${name} uninstalled`);
|
||||
setInstalledPhotoPacks(getInstalledPhotoPacks());
|
||||
window.dispatchEvent(new window.Event('installedAddonsChanged'));
|
||||
};
|
||||
|
||||
// Navigate to photo packs marketplace
|
||||
const goToPhotoPacks = () => {
|
||||
variables.updateHash('#discover/photo_packs');
|
||||
const event = new window.Event('popstate');
|
||||
window.dispatchEvent(event);
|
||||
};
|
||||
|
||||
const handleToggle = (pack) => {
|
||||
// Navigate to discover tab with the item
|
||||
const itemId = pack.name;
|
||||
updateHash(`#discover/all?item=${itemId}`);
|
||||
|
||||
// Trigger navigation
|
||||
const event = new window.Event('popstate');
|
||||
window.dispatchEvent(event);
|
||||
|
||||
variables.stats.postEvent('marketplace', 'ItemPage viewed');
|
||||
};
|
||||
|
||||
// Get total count of photos across all installed packs
|
||||
const getTotalPhotoCount = () => {
|
||||
return installedPhotoPacks.reduce((total, pack) => {
|
||||
return total + (pack.photos?.length || 0);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
const getBackgroundSettings = () => {
|
||||
switch (backgroundType) {
|
||||
case 'custom':
|
||||
@@ -231,11 +296,16 @@ const BackgroundOptions = memo(({ currentSubSection, onSubSectionChange, section
|
||||
<SourceSection
|
||||
backgroundType={backgroundType}
|
||||
marketplaceEnabled={marketplaceEnabled}
|
||||
installedPhotoPacks={installedPhotoPacks}
|
||||
totalPhotoCount={getTotalPhotoCount()}
|
||||
onTypeChange={(value) => {
|
||||
// Clear prefetch queue when changing background type
|
||||
clearQueuesOnSettingChange('backgroundType');
|
||||
setBackgroundType(value);
|
||||
}}
|
||||
onPhotoPackUninstall={handlePhotoPackUninstall}
|
||||
onGoToPhotoPacks={goToPhotoPacks}
|
||||
onToggle={handleToggle}
|
||||
/>
|
||||
{getBackgroundSettings()}
|
||||
</>
|
||||
|
||||
@@ -1,25 +1,67 @@
|
||||
import variables from 'config/variables';
|
||||
import { MdExplore } from 'react-icons/md';
|
||||
import { Dropdown } from 'components/Form/Settings';
|
||||
import { Row, Content, Action } from 'components/Layout/Settings/Item';
|
||||
import { Button } from 'components/Elements';
|
||||
import Items from 'features/marketplace/components/Items/Items';
|
||||
import { getBackgroundOptionItems } from '../optionTypes';
|
||||
|
||||
const SourceSection = ({ backgroundType, marketplaceEnabled, onTypeChange }) => {
|
||||
const SourceSection = ({
|
||||
backgroundType,
|
||||
marketplaceEnabled,
|
||||
installedPhotoPacks = [],
|
||||
totalPhotoCount = 0,
|
||||
onTypeChange,
|
||||
onPhotoPackUninstall,
|
||||
onGoToPhotoPacks,
|
||||
onToggle,
|
||||
}) => {
|
||||
const showInstalledPhotoPacks =
|
||||
backgroundType === 'photo_pack' &&
|
||||
marketplaceEnabled &&
|
||||
installedPhotoPacks.length > 0;
|
||||
|
||||
return (
|
||||
<Row final={backgroundType === 'random_colour' || backgroundType === 'random_gradient'}>
|
||||
<Content
|
||||
title={variables.getMessage('modals.main.settings.sections.background.source.title')}
|
||||
subtitle={variables.getMessage('modals.main.settings.sections.background.source.subtitle')}
|
||||
/>
|
||||
<Action>
|
||||
<Dropdown
|
||||
label={variables.getMessage('modals.main.settings.sections.background.type.title')}
|
||||
name="backgroundType"
|
||||
onChange={onTypeChange}
|
||||
category="background"
|
||||
items={getBackgroundOptionItems(marketplaceEnabled)}
|
||||
<>
|
||||
<Row final={!showInstalledPhotoPacks && (backgroundType === 'random_colour' || backgroundType === 'random_gradient')}>
|
||||
<Content
|
||||
title={variables.getMessage('modals.main.settings.sections.background.source.title')}
|
||||
subtitle={variables.getMessage('modals.main.settings.sections.background.source.subtitle')}
|
||||
/>
|
||||
</Action>
|
||||
</Row>
|
||||
<Action>
|
||||
<Dropdown
|
||||
label={variables.getMessage('modals.main.settings.sections.background.type.title')}
|
||||
name="backgroundType"
|
||||
onChange={onTypeChange}
|
||||
category="background"
|
||||
items={getBackgroundOptionItems(marketplaceEnabled)}
|
||||
/>
|
||||
</Action>
|
||||
</Row>
|
||||
|
||||
{showInstalledPhotoPacks && (
|
||||
<>
|
||||
<Row final={true}>
|
||||
<Content
|
||||
title={variables.getMessage('modals.main.settings.sections.background.installed_packs_title')}
|
||||
subtitle={`${installedPhotoPacks.length} ${installedPhotoPacks.length === 1 ? 'pack' : 'packs'} • ${totalPhotoCount} ${totalPhotoCount === 1 ? 'photo' : 'photos'}`}
|
||||
/>
|
||||
<Action>
|
||||
<Button onClick={onGoToPhotoPacks} icon={<MdExplore />} label="Get more" />
|
||||
</Action>
|
||||
</Row>
|
||||
<Items
|
||||
items={installedPhotoPacks}
|
||||
isAdded={true}
|
||||
filter=""
|
||||
toggleFunction={onToggle}
|
||||
showCreateYourOwn={false}
|
||||
onUninstall={onPhotoPackUninstall}
|
||||
viewType="grid"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -113,14 +113,19 @@ export function useQuoteLoader(updateQuote) {
|
||||
];
|
||||
}
|
||||
|
||||
if (!customQuote || customQuote.length === 0) {
|
||||
// Filter out incomplete quotes (empty quote text)
|
||||
const validQuotes = customQuote?.filter(
|
||||
(q) => q.quote && q.quote.trim() !== ''
|
||||
) || [];
|
||||
|
||||
if (validQuotes.length === 0) {
|
||||
return { noQuote: true };
|
||||
}
|
||||
|
||||
const selected = customQuote[Math.floor(Math.random() * customQuote.length)];
|
||||
const selected = validQuotes[Math.floor(Math.random() * validQuotes.length)];
|
||||
return {
|
||||
quote: `"${selected.quote}"`,
|
||||
author: selected.author,
|
||||
author: selected.author || 'Unknown',
|
||||
authorlink: getAuthorLink(selected.author),
|
||||
needsAuthorData: true,
|
||||
noQuote: false,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import variables from 'config/variables';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { MdCancel, MdAdd, MdSource, MdOutlineFormatQuote } from 'react-icons/md';
|
||||
import { MdCancel, MdAdd, MdSource, MdOutlineFormatQuote, MdExplore } from 'react-icons/md';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import {
|
||||
Header,
|
||||
@@ -13,6 +14,9 @@ import {
|
||||
import { Checkbox, Dropdown, Textarea } from 'components/Form/Settings';
|
||||
import { Button } from 'components/Elements';
|
||||
import { FREQUENCY_OPTIONS } from 'utils/frequencyManager';
|
||||
import Items from 'features/marketplace/components/Items/Items';
|
||||
import { uninstall } from 'utils/marketplace';
|
||||
import { updateHash } from 'utils/deepLinking';
|
||||
import './QuoteOptions.scss';
|
||||
|
||||
const QuoteOptions = ({ currentSubSection, onSubSectionChange, sectionName }) => {
|
||||
@@ -192,6 +196,78 @@ const QuoteOptions = ({ currentSubSection, onSubSectionChange, sectionName }) =>
|
||||
|
||||
const isSourceSection = currentSubSection === 'source';
|
||||
|
||||
// Get installed quote packs
|
||||
const getInstalledQuotePacks = () => {
|
||||
try {
|
||||
const installed = JSON.parse(localStorage.getItem('installed')) || [];
|
||||
return installed.filter((item) => item.type === 'quotes');
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const [installedQuotePacks, setInstalledQuotePacks] = useState(getInstalledQuotePacks());
|
||||
|
||||
// Listen for changes to installed addons
|
||||
useEffect(() => {
|
||||
const handleInstalledAddonsChanged = () => {
|
||||
setInstalledQuotePacks(getInstalledQuotePacks());
|
||||
// Update quoteType if it changed (e.g., when all packs are uninstalled)
|
||||
const currentType = localStorage.getItem('quoteType') || 'api';
|
||||
if (currentType !== quoteType) {
|
||||
setQuoteType(currentType);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('installedAddonsChanged', handleInstalledAddonsChanged);
|
||||
return () => {
|
||||
window.removeEventListener('installedAddonsChanged', handleInstalledAddonsChanged);
|
||||
};
|
||||
}, [quoteType]);
|
||||
|
||||
const handleUninstall = (type, name) => {
|
||||
// Prevent removing the default pack if it's the only one remaining
|
||||
const DEFAULT_PACK_ID = '0c8a5bdebd13';
|
||||
if (installedQuotePacks.length === 1) {
|
||||
const remainingPack = installedQuotePacks[0];
|
||||
if (remainingPack.id === DEFAULT_PACK_ID || remainingPack.name === name) {
|
||||
toast(variables.getMessage('toasts.quote_pack_only_one'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uninstall(type, name);
|
||||
toast(variables.getMessage('toasts.uninstalled'));
|
||||
variables.stats.postEvent('marketplace-item', `${name} uninstalled`);
|
||||
variables.stats.postEvent('marketplace', 'Uninstall');
|
||||
setInstalledQuotePacks(getInstalledQuotePacks());
|
||||
window.dispatchEvent(new window.Event('installedAddonsChanged'));
|
||||
};
|
||||
|
||||
const goToQuotePacks = () => {
|
||||
updateHash('#discover/quote_packs');
|
||||
const event = new window.Event('popstate');
|
||||
window.dispatchEvent(event);
|
||||
};
|
||||
|
||||
const handleToggle = (pack) => {
|
||||
// Navigate to discover tab with the item
|
||||
const itemId = pack.name;
|
||||
updateHash(`#discover/all?item=${itemId}`);
|
||||
|
||||
// Trigger navigation
|
||||
const event = new window.Event('popstate');
|
||||
window.dispatchEvent(event);
|
||||
|
||||
variables.stats.postEvent('marketplace', 'ItemPage viewed');
|
||||
};
|
||||
|
||||
const getTotalQuoteCount = () => {
|
||||
return installedQuotePacks.reduce((total, pack) => {
|
||||
return total + (pack.quotes?.length || 0);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
let customSettings;
|
||||
if (quoteType === 'custom' && isSourceSection) {
|
||||
customSettings = (
|
||||
@@ -277,6 +353,35 @@ const QuoteOptions = ({ currentSubSection, onSubSectionChange, sectionName }) =>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
} else if (quoteType === 'quote_pack' && isSourceSection && installedQuotePacks.length > 0) {
|
||||
const totalQuotes = getTotalQuoteCount();
|
||||
customSettings = (
|
||||
<>
|
||||
<Row final={true}>
|
||||
<Content
|
||||
title={variables.getMessage('modals.main.settings.sections.quote.installed_packs_title')}
|
||||
subtitle={`${installedQuotePacks.length} ${installedQuotePacks.length === 1 ? 'pack' : 'packs'} • ${totalQuotes} ${totalQuotes === 1 ? 'quote' : 'quotes'}`}
|
||||
/>
|
||||
<Action>
|
||||
<Button
|
||||
type="settings"
|
||||
onClick={goToQuotePacks}
|
||||
icon={<MdExplore />}
|
||||
label={variables.getMessage('modals.main.settings.sections.quote.get_more')}
|
||||
/>
|
||||
</Action>
|
||||
</Row>
|
||||
<Items
|
||||
items={installedQuotePacks}
|
||||
isAdded={true}
|
||||
filter=""
|
||||
toggleFunction={handleToggle}
|
||||
showCreateYourOwn={false}
|
||||
onUninstall={handleUninstall}
|
||||
viewType="grid"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
// api
|
||||
customSettings = <></>;
|
||||
|
||||
Reference in New Issue
Block a user