Add ml search config to enable or disable ml search
Show ml search ui elements when enabled
This commit is contained in:
parent
b21e5608bd
commit
8c0c3c5c94
|
@ -1,4 +1,4 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import React, { useContext, useEffect, useRef, useState } from 'react';
|
||||
import Photoswipe from 'photoswipe';
|
||||
import PhotoswipeUIDefault from 'photoswipe/dist/photoswipe-ui-default';
|
||||
import classnames from 'classnames';
|
||||
|
@ -49,6 +49,7 @@ import { Formik } from 'formik';
|
|||
import * as Yup from 'yup';
|
||||
import EnteSpinner from 'components/EnteSpinner';
|
||||
import EnteDateTimePicker from 'components/EnteDateTimePicker';
|
||||
import { AppContext } from 'pages/_app';
|
||||
|
||||
interface Iprops {
|
||||
isOpen: boolean;
|
||||
|
@ -397,6 +398,7 @@ function InfoModal({
|
|||
exif,
|
||||
scheduleUpdate,
|
||||
}) {
|
||||
const appContext = useContext(AppContext);
|
||||
return (
|
||||
<Modal show={showInfo} onHide={handleCloseInfo}>
|
||||
<Modal.Header closeButton>
|
||||
|
@ -438,16 +440,22 @@ function InfoModal({
|
|||
{constants.SHOW_MAP}
|
||||
</a>
|
||||
)}
|
||||
{appContext.mlSearchEnabled && (
|
||||
<>
|
||||
<div>
|
||||
<Legend>{constants.PEOPLE}</Legend>
|
||||
</div>
|
||||
<PhotoPeopleList file={items[photoSwipe?.getCurrentIndex()]} />
|
||||
<PhotoPeopleList
|
||||
file={items[photoSwipe?.getCurrentIndex()]}
|
||||
/>
|
||||
<div>
|
||||
<Legend>{constants.UNIDENTIFIED_FACES}</Legend>
|
||||
</div>
|
||||
<UnidentifiedFaces
|
||||
file={items[photoSwipe?.getCurrentIndex()]}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{exif && (
|
||||
<>
|
||||
<ExifData exif={exif} />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Search, SearchStats } from 'pages/gallery';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import React, { useContext, useEffect, useRef, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import AsyncSelect from 'react-select/async';
|
||||
import { components } from 'react-select';
|
||||
|
@ -28,6 +28,7 @@ import VideoIcon from './icons/VideoIcon';
|
|||
import { IconButton } from './Container';
|
||||
import { Person } from 'types/machineLearning';
|
||||
import { PeopleList } from './MachineLearning/PeopleList';
|
||||
import { AppContext } from 'pages/_app';
|
||||
|
||||
const Wrapper = styled.div<{ isDisabled: boolean; isOpen: boolean }>`
|
||||
position: fixed;
|
||||
|
@ -118,6 +119,7 @@ interface Props {
|
|||
export default function SearchBar(props: Props) {
|
||||
const selectRef = useRef(null);
|
||||
const [value, setValue] = useState<Suggestion>(null);
|
||||
const appContext = useContext(AppContext);
|
||||
|
||||
const handleChange = (value) => {
|
||||
setValue(value);
|
||||
|
@ -129,12 +131,14 @@ export default function SearchBar(props: Props) {
|
|||
// Functionality
|
||||
// = =========================
|
||||
const getAutoCompleteSuggestions = async (searchPhrase: string) => {
|
||||
const options = await getAllPeopleSuggestion();
|
||||
// const options = [];
|
||||
const options = [];
|
||||
searchPhrase = searchPhrase.trim().toLowerCase();
|
||||
if (!searchPhrase?.length) {
|
||||
return [];
|
||||
}
|
||||
if (appContext.mlSearchEnabled) {
|
||||
options.push(...(await getAllPeopleSuggestion()));
|
||||
}
|
||||
options.push(...getHolidaySuggestion(searchPhrase));
|
||||
options.push(...getYearSuggestion(searchPhrase));
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ import {
|
|||
TRASH_SECTION,
|
||||
} from 'components/pages/gallery/Collections';
|
||||
import FixLargeThumbnails from './FixLargeThumbnail';
|
||||
import { AppContext } from 'pages/_app';
|
||||
interface Props {
|
||||
collections: Collection[];
|
||||
setDialogMessage: SetDialogMessage;
|
||||
|
@ -56,6 +57,7 @@ export default function Sidebar(props: Props) {
|
|||
const [exportModalView, setExportModalView] = useState(false);
|
||||
const [fixLargeThumbsView, setFixLargeThumbsView] = useState(false);
|
||||
const galleryContext = useContext(GalleryContext);
|
||||
const appContext = useContext(AppContext);
|
||||
useEffect(() => {
|
||||
const main = async () => {
|
||||
if (!isOpen) {
|
||||
|
@ -297,6 +299,17 @@ export default function Sidebar(props: Props) {
|
|||
onClick={openFeedbackURL}>
|
||||
{constants.REQUEST_FEATURE}
|
||||
</LinkButton>
|
||||
<LinkButton
|
||||
style={{ marginTop: '30px' }}
|
||||
onClick={() => {
|
||||
appContext.updateMlSearchEnabled(
|
||||
!appContext.mlSearchEnabled
|
||||
);
|
||||
}}>
|
||||
{appContext.mlSearchEnabled
|
||||
? constants.DISABLE_ML_SEARCH
|
||||
: constants.ENABLE_ML_SEARCH}
|
||||
</LinkButton>
|
||||
<LinkButton
|
||||
style={{ marginTop: '30px' }}
|
||||
onClick={() => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { JobConfig } from 'types/common/job';
|
||||
import { MLSyncConfig } from 'types/machineLearning';
|
||||
import { MLSearchConfig, MLSyncConfig } from 'types/machineLearning';
|
||||
|
||||
export const DEFAULT_ML_SYNC_JOB_CONFIG: JobConfig = {
|
||||
intervalSec: 30,
|
||||
|
@ -53,6 +53,10 @@ export const DEFAULT_ML_SYNC_CONFIG: MLSyncConfig = {
|
|||
mlVersion: 2,
|
||||
};
|
||||
|
||||
export const DEFAULT_ML_SEARCH_CONFIG: MLSearchConfig = {
|
||||
enabled: false,
|
||||
};
|
||||
|
||||
export const ML_SYNC_DOWNLOAD_TIMEOUT_MS = 300000;
|
||||
|
||||
export const MAX_FACE_DISTANCE_PERCENT = Math.sqrt(2) / 100;
|
||||
|
|
|
@ -16,6 +16,10 @@ import FlashMessageBar from 'components/FlashMessageBar';
|
|||
import Head from 'next/head';
|
||||
import { eventBus, Events } from 'services/events';
|
||||
import mlWorkManager from 'services/machineLearning/mlWorkManager';
|
||||
import {
|
||||
getMLSearchConfig,
|
||||
updateMLSearchConfig,
|
||||
} from 'utils/machineLearning/config';
|
||||
|
||||
const GlobalStyles = createGlobalStyle`
|
||||
/* ubuntu-regular - latin */
|
||||
|
@ -483,6 +487,8 @@ type AppContextType = {
|
|||
setDisappearingFlashMessage: (message: FlashMessage) => void;
|
||||
redirectUrl: string;
|
||||
setRedirectUrl: (url: string) => void;
|
||||
mlSearchEnabled: boolean;
|
||||
updateMlSearchEnabled: (enabled: boolean) => void;
|
||||
};
|
||||
|
||||
export enum FLASH_MESSAGE_TYPE {
|
||||
|
@ -513,6 +519,7 @@ export default function App({ Component, err }) {
|
|||
const [redirectName, setRedirectName] = useState<string>(null);
|
||||
const [flashMessage, setFlashMessage] = useState<FlashMessage>(null);
|
||||
const [redirectUrl, setRedirectUrl] = useState(null);
|
||||
const [mlSearchEnabled, setMlSearchEnabled] = useState(false);
|
||||
useEffect(() => {
|
||||
if (
|
||||
!('serviceWorker' in navigator) ||
|
||||
|
@ -550,12 +557,18 @@ export default function App({ Component, err }) {
|
|||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const loadMlSearchState = async () => {
|
||||
try {
|
||||
mlWorkManager;
|
||||
const mlSearchConfig = await getMLSearchConfig();
|
||||
setMlSearchEnabled(mlSearchConfig.enabled);
|
||||
mlWorkManager.setMlSearchEnabled(mlSearchConfig.enabled);
|
||||
eventBus.emit(Events.APP_START);
|
||||
} catch (e) {
|
||||
logError(e, 'Error in appStart handlers');
|
||||
}
|
||||
};
|
||||
|
||||
loadMlSearchState();
|
||||
}, []);
|
||||
|
||||
const setUserOnline = () => setOffline(false);
|
||||
|
@ -612,6 +625,13 @@ export default function App({ Component, err }) {
|
|||
setFlashMessage(flashMessages);
|
||||
setTimeout(() => setFlashMessage(null), 5000);
|
||||
};
|
||||
const updateMlSearchEnabled = async (enabled: boolean) => {
|
||||
const mlSearchConfig = await getMLSearchConfig();
|
||||
mlSearchConfig.enabled = enabled;
|
||||
await updateMLSearchConfig(mlSearchConfig);
|
||||
setMlSearchEnabled(enabled);
|
||||
mlWorkManager.setMlSearchEnabled(enabled);
|
||||
};
|
||||
// ho ja yaar
|
||||
return (
|
||||
<>
|
||||
|
@ -657,6 +677,8 @@ export default function App({ Component, err }) {
|
|||
setDisappearingFlashMessage,
|
||||
redirectUrl,
|
||||
setRedirectUrl,
|
||||
mlSearchEnabled,
|
||||
updateMlSearchEnabled,
|
||||
}}>
|
||||
{loading ? (
|
||||
<Container>
|
||||
|
|
|
@ -19,8 +19,12 @@ class MLWorkManager {
|
|||
private mlSyncJob: MLSyncJob;
|
||||
private syncJobWorker: MLWorkerWithProxy;
|
||||
|
||||
private debouncedLiveSyncIdle: () => void;
|
||||
private debouncedFilesUpdated: () => void;
|
||||
|
||||
private liveSyncQueue: PQueue;
|
||||
private liveSyncWorker: MLWorkerWithProxy;
|
||||
private mlSearchEnabled: boolean;
|
||||
|
||||
constructor() {
|
||||
this.liveSyncQueue = new PQueue({
|
||||
|
@ -29,31 +33,58 @@ class MLWorkManager {
|
|||
timeout: LIVE_SYNC_QUEUE_TIMEOUT_SEC * 1000,
|
||||
throwOnTimeout: true,
|
||||
});
|
||||
logQueueStats(this.liveSyncQueue, 'livesync');
|
||||
this.mlSearchEnabled = false;
|
||||
|
||||
const debouncedLiveSyncIdle = debounce(
|
||||
eventBus.on(Events.LOGOUT, this.logoutHandler, this);
|
||||
this.debouncedLiveSyncIdle = debounce(
|
||||
() => this.onLiveSyncIdle(),
|
||||
LIVE_SYNC_IDLE_DEBOUNCE_SEC * 1000
|
||||
);
|
||||
this.liveSyncQueue.on('idle', () => debouncedLiveSyncIdle(), this);
|
||||
|
||||
eventBus.on(Events.APP_START, this.appStartHandler, this);
|
||||
|
||||
eventBus.on(Events.LOGIN, this.startSyncJob, this);
|
||||
|
||||
eventBus.on(Events.LOGOUT, this.logoutHandler, this);
|
||||
|
||||
eventBus.on(Events.FILE_UPLOADED, this.fileUploadedHandler, this);
|
||||
|
||||
const debouncedFilesUpdated = debounce(
|
||||
() => this.localFilesUpdatedHandler(),
|
||||
this.debouncedFilesUpdated = debounce(
|
||||
() => this.mlSearchEnabled && this.localFilesUpdatedHandler(),
|
||||
LOCAL_FILES_UPDATED_DEBOUNCE_SEC * 1000
|
||||
);
|
||||
}
|
||||
|
||||
public async setMlSearchEnabled(enabled: boolean) {
|
||||
if (!this.mlSearchEnabled && enabled) {
|
||||
console.log('Enabling MLWorkManager');
|
||||
this.mlSearchEnabled = true;
|
||||
|
||||
logQueueStats(this.liveSyncQueue, 'livesync');
|
||||
this.liveSyncQueue.on('idle', this.debouncedLiveSyncIdle, this);
|
||||
|
||||
// eventBus.on(Events.APP_START, this.appStartHandler, this);
|
||||
// eventBus.on(Events.LOGIN, this.startSyncJob, this);
|
||||
eventBus.on(Events.FILE_UPLOADED, this.fileUploadedHandler, this);
|
||||
eventBus.on(
|
||||
Events.LOCAL_FILES_UPDATED,
|
||||
() => debouncedFilesUpdated(),
|
||||
this.debouncedFilesUpdated,
|
||||
this
|
||||
);
|
||||
|
||||
await this.startSyncJob();
|
||||
} else if (this.mlSearchEnabled && !enabled) {
|
||||
console.log('Disabling MLWorkManager');
|
||||
this.mlSearchEnabled = false;
|
||||
|
||||
this.liveSyncQueue.removeAllListeners();
|
||||
|
||||
// eventBus.removeListener(Events.APP_START, this.appStartHandler, this);
|
||||
// eventBus.removeListener(Events.LOGIN, this.startSyncJob, this);
|
||||
eventBus.removeListener(
|
||||
Events.FILE_UPLOADED,
|
||||
this.fileUploadedHandler,
|
||||
this
|
||||
);
|
||||
eventBus.removeListener(
|
||||
Events.LOCAL_FILES_UPDATED,
|
||||
this.debouncedFilesUpdated,
|
||||
this
|
||||
);
|
||||
|
||||
await this.stopSyncJob();
|
||||
}
|
||||
}
|
||||
|
||||
// Handlers
|
||||
|
@ -83,6 +114,9 @@ class MLWorkManager {
|
|||
enteFile: File;
|
||||
localFile: globalThis.File;
|
||||
}) {
|
||||
if (!this.mlSearchEnabled) {
|
||||
return;
|
||||
}
|
||||
console.log('fileUploadedHandler: ', arg.enteFile.id);
|
||||
if (arg.enteFile.metadata.fileType !== FILE_TYPE.IMAGE) {
|
||||
console.log('Skipping non image file for local file processing');
|
||||
|
@ -131,7 +165,7 @@ class MLWorkManager {
|
|||
private async onLiveSyncIdle() {
|
||||
console.log('Live sync idle');
|
||||
await this.terminateLiveSyncWorker();
|
||||
this.startSyncJob();
|
||||
this.mlSearchEnabled && this.startSyncJob();
|
||||
}
|
||||
|
||||
public async syncLocalFile(enteFile: File, localFile: globalThis.File) {
|
||||
|
@ -185,6 +219,10 @@ class MLWorkManager {
|
|||
public async startSyncJob() {
|
||||
try {
|
||||
console.log('MLWorkManager.startSyncJob');
|
||||
if (!this.mlSearchEnabled) {
|
||||
console.log('ML Search disabled, not starting ml sync job');
|
||||
return;
|
||||
}
|
||||
if (!getToken()) {
|
||||
console.log('User not logged in, not starting ml sync job');
|
||||
return;
|
||||
|
|
|
@ -244,6 +244,10 @@ export interface MLSyncConfig extends Config {
|
|||
mlVersion: number;
|
||||
}
|
||||
|
||||
export interface MLSearchConfig extends Config {
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface MLSyncContext {
|
||||
token: string;
|
||||
config: MLSyncConfig;
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import {
|
||||
DEFAULT_ML_SEARCH_CONFIG,
|
||||
DEFAULT_ML_SYNC_CONFIG,
|
||||
DEFAULT_ML_SYNC_JOB_CONFIG,
|
||||
} from 'constants/machineLearning/config';
|
||||
import { JobConfig } from 'types/common/job';
|
||||
import { MLSyncConfig } from 'types/machineLearning';
|
||||
import { MLSearchConfig, MLSyncConfig } from 'types/machineLearning';
|
||||
import mlIDbStorage, {
|
||||
ML_SEARCH_CONFIG_NAME,
|
||||
ML_SYNC_CONFIG_NAME,
|
||||
ML_SYNC_JOB_CONFIG_NAME,
|
||||
} from 'utils/storage/mlIDbStorage';
|
||||
|
@ -20,6 +22,13 @@ export async function getMLSyncConfig() {
|
|||
return mlIDbStorage.getConfig(ML_SYNC_CONFIG_NAME, DEFAULT_ML_SYNC_CONFIG);
|
||||
}
|
||||
|
||||
export async function getMLSearchConfig() {
|
||||
return mlIDbStorage.getConfig(
|
||||
ML_SEARCH_CONFIG_NAME,
|
||||
DEFAULT_ML_SEARCH_CONFIG
|
||||
);
|
||||
}
|
||||
|
||||
export async function updateMLSyncJobConfig(newConfig: JobConfig) {
|
||||
return mlIDbStorage.putConfig(ML_SYNC_JOB_CONFIG_NAME, newConfig);
|
||||
}
|
||||
|
@ -27,3 +36,7 @@ export async function updateMLSyncJobConfig(newConfig: JobConfig) {
|
|||
export async function updateMLSyncConfig(newConfig: MLSyncConfig) {
|
||||
return mlIDbStorage.putConfig(ML_SYNC_CONFIG_NAME, newConfig);
|
||||
}
|
||||
|
||||
export async function updateMLSearchConfig(newConfig: MLSearchConfig) {
|
||||
return mlIDbStorage.putConfig(ML_SEARCH_CONFIG_NAME, newConfig);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import {
|
||||
DEFAULT_ML_SEARCH_CONFIG,
|
||||
DEFAULT_ML_SYNC_CONFIG,
|
||||
DEFAULT_ML_SYNC_JOB_CONFIG,
|
||||
} from 'constants/machineLearning/config';
|
||||
|
@ -16,6 +17,7 @@ import { runningInBrowser } from 'utils/common';
|
|||
|
||||
export const ML_SYNC_JOB_CONFIG_NAME = 'ml-sync-job';
|
||||
export const ML_SYNC_CONFIG_NAME = 'ml-sync';
|
||||
export const ML_SEARCH_CONFIG_NAME = 'ml-search';
|
||||
|
||||
const MLDATA_DB_NAME = 'mldata';
|
||||
interface MLDb extends DBSchema {
|
||||
|
@ -50,7 +52,7 @@ class MLIDbStorage {
|
|||
return;
|
||||
}
|
||||
|
||||
this.db = openDB<MLDb>(MLDATA_DB_NAME, 2, {
|
||||
this.db = openDB<MLDb>(MLDATA_DB_NAME, 3, {
|
||||
upgrade(db, oldVersion, newVersion, tx) {
|
||||
if (oldVersion < 1) {
|
||||
const filesStore = db.createObjectStore('files', {
|
||||
|
@ -82,6 +84,12 @@ class MLIDbStorage {
|
|||
ML_SYNC_CONFIG_NAME
|
||||
);
|
||||
}
|
||||
if (oldVersion < 3) {
|
||||
tx.objectStore('configs').add(
|
||||
DEFAULT_ML_SEARCH_CONFIG,
|
||||
ML_SEARCH_CONFIG_NAME
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -204,6 +204,8 @@ const englishConstants = {
|
|||
),
|
||||
CONTACT_SUPPORT: 'contact support',
|
||||
REQUEST_FEATURE: 'request feature',
|
||||
ENABLE_ML_SEARCH: 'enable ML Search beta',
|
||||
DISABLE_ML_SEARCH: 'disable ML Search beta',
|
||||
ML_DEBUG: 'ML Debug',
|
||||
SUPPORT: 'support',
|
||||
CONFIRM: 'confirm',
|
||||
|
|
Loading…
Reference in a new issue