mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-11-27 18:12:54 +03:00
Merge pull request #8860 from toeverything/eyhn/affine-intelligent-integrated
feat(mobile): integrate ai button
This commit is contained in:
commit
442c86011a
@ -9,6 +9,7 @@
|
||||
/* Begin PBXBuildFile section */
|
||||
505B0A342CEB3FB10092FC35 /* Intelligents in Frameworks */ = {isa = PBXBuildFile; productRef = 505B0A332CEB3FB10092FC35 /* Intelligents */; };
|
||||
505B0A362CEB48B10092FC35 /* RootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505B0A352CEB48B10092FC35 /* RootViewController.swift */; };
|
||||
9D1C07272CEC3E9500E1C502 /* IntelligentsPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D1C07262CEC3E8200E1C502 /* IntelligentsPlugin.swift */; };
|
||||
9D6A85332CCF6DA700DAB35F /* HashcashPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D6A85322CCF6DA700DAB35F /* HashcashPlugin.swift */; };
|
||||
9D90BE252CCB9876006677DB /* CookieManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D90BE172CCB9876006677DB /* CookieManager.swift */; };
|
||||
9D90BE262CCB9876006677DB /* CookiePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D90BE182CCB9876006677DB /* CookiePlugin.swift */; };
|
||||
@ -26,6 +27,7 @@
|
||||
504EC3041FED79650016851F /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
505B0A312CEB3FAB0092FC35 /* Intelligents */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Intelligents; sourceTree = "<group>"; };
|
||||
505B0A352CEB48B10092FC35 /* RootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootViewController.swift; sourceTree = "<group>"; };
|
||||
9D1C07262CEC3E8200E1C502 /* IntelligentsPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntelligentsPlugin.swift; sourceTree = "<group>"; };
|
||||
9D6A85322CCF6DA700DAB35F /* HashcashPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashcashPlugin.swift; sourceTree = "<group>"; };
|
||||
9D90BE172CCB9876006677DB /* CookieManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CookieManager.swift; sourceTree = "<group>"; };
|
||||
9D90BE182CCB9876006677DB /* CookiePlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CookiePlugin.swift; sourceTree = "<group>"; };
|
||||
@ -102,6 +104,7 @@
|
||||
9D90BE192CCB9876006677DB /* Cookie */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9D1C07262CEC3E8200E1C502 /* IntelligentsPlugin.swift */,
|
||||
9D90BE172CCB9876006677DB /* CookieManager.swift */,
|
||||
9D90BE182CCB9876006677DB /* CookiePlugin.swift */,
|
||||
9D6A85322CCF6DA700DAB35F /* HashcashPlugin.swift */,
|
||||
@ -250,6 +253,7 @@
|
||||
9D90BE252CCB9876006677DB /* CookieManager.swift in Sources */,
|
||||
9D90BE262CCB9876006677DB /* CookiePlugin.swift in Sources */,
|
||||
505B0A362CEB48B10092FC35 /* RootViewController.swift in Sources */,
|
||||
9D1C07272CEC3E9500E1C502 /* IntelligentsPlugin.swift in Sources */,
|
||||
9D6A85332CCF6DA700DAB35F /* HashcashPlugin.swift in Sources */,
|
||||
9D90BE272CCB9876006677DB /* AffineViewController.swift in Sources */,
|
||||
9D90BE282CCB9876006677DB /* AppDelegate.swift in Sources */,
|
||||
|
@ -13,16 +13,16 @@ class AFFiNEViewController: CAPBridgeViewController {
|
||||
override func capacitorDidLoad() {
|
||||
bridge?.registerPluginInstance(CookiePlugin())
|
||||
bridge?.registerPluginInstance(HashcashPlugin())
|
||||
bridge?.registerPluginInstance(IntelligentsPlugin(ui: self))
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
navigationController?.setNavigationBarHidden(false, animated: animated)
|
||||
self.presentIntelligentsButton()
|
||||
self.dismissIntelligentsButton()
|
||||
}
|
||||
|
||||
override func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
dismissIntelligentsButton()
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
// Created by 秋星桥 on 2024/11/18.
|
||||
//
|
||||
|
||||
import ColorfulX
|
||||
import UIKit
|
||||
|
||||
// floating button to open intelligent panel
|
||||
|
@ -0,0 +1,34 @@
|
||||
import Foundation
|
||||
import Capacitor
|
||||
|
||||
@objc(IntelligentsPlugin)
|
||||
public class IntelligentsPlugin: CAPPlugin, CAPBridgedPlugin {
|
||||
public let identifier = "IntelligentsPlugin"
|
||||
public let jsName = "Intelligents"
|
||||
public let pluginMethods: [CAPPluginMethod] = [
|
||||
CAPPluginMethod(name: "presentIntelligentsButton", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "dismissIntelligentsButton", returnType: CAPPluginReturnPromise)
|
||||
]
|
||||
public let ui: UIViewController
|
||||
|
||||
init(ui: UIViewController) {
|
||||
self.ui = ui
|
||||
super.init()
|
||||
}
|
||||
|
||||
@objc public func presentIntelligentsButton(_ call: CAPPluginCall) {
|
||||
DispatchQueue.main.async {
|
||||
self.ui.presentIntelligentsButton()
|
||||
print("!!!!!!!!!!!!present")
|
||||
call.resolve()
|
||||
}
|
||||
}
|
||||
|
||||
@objc public func dismissIntelligentsButton(_ call: CAPPluginCall) {
|
||||
DispatchQueue.main.async {
|
||||
self.ui.dismissIntelligentsButton()
|
||||
print("!!!!!!!!!!!!dismiss")
|
||||
call.resolve()
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ import { AppContainer } from '@affine/core/desktop/components/app-container';
|
||||
import { configureMobileModules } from '@affine/core/mobile/modules';
|
||||
import { router } from '@affine/core/mobile/router';
|
||||
import { configureCommonModules } from '@affine/core/modules';
|
||||
import { AIButtonProvider } from '@affine/core/modules/ai-button';
|
||||
import {
|
||||
AuthService,
|
||||
ValidatorProvider,
|
||||
@ -32,6 +33,7 @@ import { RouterProvider } from 'react-router-dom';
|
||||
import { configureFetchProvider } from './fetch';
|
||||
import { Cookie } from './plugins/cookie';
|
||||
import { Hashcash } from './plugins/hashcash';
|
||||
import { Intelligents } from './plugins/intelligents';
|
||||
|
||||
const future = {
|
||||
v7_startTransition: true,
|
||||
@ -76,6 +78,14 @@ framework.impl(ValidatorProvider, {
|
||||
return res.value;
|
||||
},
|
||||
});
|
||||
framework.impl(AIButtonProvider, {
|
||||
presentAIButton: () => {
|
||||
return Intelligents.presentIntelligentsButton();
|
||||
},
|
||||
dismissAIButton: () => {
|
||||
return Intelligents.dismissIntelligentsButton();
|
||||
},
|
||||
});
|
||||
const frameworkProvider = framework.provider();
|
||||
|
||||
// setup application lifecycle events, and emit application start event
|
||||
|
@ -0,0 +1,4 @@
|
||||
export interface IntelligentsPlugin {
|
||||
presentIntelligentsButton(): Promise<void>;
|
||||
dismissIntelligentsButton(): Promise<void>;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
import { registerPlugin } from '@capacitor/core';
|
||||
|
||||
import type { IntelligentsPlugin } from './definitions';
|
||||
|
||||
const Intelligents = registerPlugin<IntelligentsPlugin>('Intelligents');
|
||||
|
||||
export * from './definitions';
|
||||
export { Intelligents };
|
@ -10,6 +10,7 @@ import { useNavigateHelper } from '@affine/core/components/hooks/use-navigate-he
|
||||
import { PageHeader } from '@affine/core/components/mobile';
|
||||
import { PageDetailEditor } from '@affine/core/components/page-detail-editor';
|
||||
import { DetailPageWrapper } from '@affine/core/desktop/pages/workspace/detail-page/detail-page-wrapper';
|
||||
import { AIButtonService } from '@affine/core/modules/ai-button';
|
||||
import { EditorService } from '@affine/core/modules/editor';
|
||||
import { JournalService } from '@affine/core/modules/journal';
|
||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||
@ -56,6 +57,7 @@ const DetailPageImpl = () => {
|
||||
workspaceService,
|
||||
globalContextService,
|
||||
featureFlagService,
|
||||
aIButtonService,
|
||||
} = useServices({
|
||||
WorkbenchService,
|
||||
ViewService,
|
||||
@ -64,6 +66,7 @@ const DetailPageImpl = () => {
|
||||
WorkspaceService,
|
||||
GlobalContextService,
|
||||
FeatureFlagService,
|
||||
AIButtonService,
|
||||
});
|
||||
const editor = editorService.editor;
|
||||
const workspace = workspaceService.workspace;
|
||||
@ -108,6 +111,14 @@ const DetailPageImpl = () => {
|
||||
};
|
||||
}, [doc, globalContext, mode]);
|
||||
|
||||
useEffect(() => {
|
||||
aIButtonService.presentAIButton(true);
|
||||
|
||||
return () => {
|
||||
aIButtonService.presentAIButton(false);
|
||||
};
|
||||
}, [aIButtonService]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!enableKeyboardToolbar) setDocReadonly(doc.id, true);
|
||||
}, [enableKeyboardToolbar, doc.id, setDocReadonly]);
|
||||
|
13
packages/frontend/core/src/modules/ai-button/index.ts
Normal file
13
packages/frontend/core/src/modules/ai-button/index.ts
Normal file
@ -0,0 +1,13 @@
|
||||
export { AIButtonProvider } from './provider/ai-button';
|
||||
export { AIButtonService } from './services/ai-button';
|
||||
|
||||
import type { Framework } from '@toeverything/infra';
|
||||
|
||||
import { AIButtonProvider } from './provider/ai-button';
|
||||
import { AIButtonService } from './services/ai-button';
|
||||
|
||||
export const configureAIButtonModule = (framework: Framework) => {
|
||||
framework.service(AIButtonService, container => {
|
||||
return new AIButtonService(container.getOptional(AIButtonProvider));
|
||||
});
|
||||
};
|
@ -0,0 +1,9 @@
|
||||
import { createIdentifier } from '@toeverything/infra';
|
||||
|
||||
export interface AIButtonProvider {
|
||||
presentAIButton: () => Promise<void>;
|
||||
dismissAIButton: () => Promise<void>;
|
||||
}
|
||||
|
||||
export const AIButtonProvider =
|
||||
createIdentifier<AIButtonProvider>('AIButtonProvider');
|
@ -0,0 +1,48 @@
|
||||
import { DebugLogger } from '@affine/debug';
|
||||
import {
|
||||
effect,
|
||||
exhaustMapWithTrailing,
|
||||
fromPromise,
|
||||
Service,
|
||||
} from '@toeverything/infra';
|
||||
import {
|
||||
catchError,
|
||||
distinctUntilChanged,
|
||||
EMPTY,
|
||||
mergeMap,
|
||||
throttleTime,
|
||||
} from 'rxjs';
|
||||
|
||||
import type { AIButtonProvider } from '../provider/ai-button';
|
||||
|
||||
const logger = new DebugLogger('AIButtonService');
|
||||
|
||||
export class AIButtonService extends Service {
|
||||
constructor(private readonly aiButtonProvider?: AIButtonProvider) {
|
||||
super();
|
||||
}
|
||||
|
||||
presentAIButton = effect(
|
||||
distinctUntilChanged(),
|
||||
throttleTime<boolean>(1000), // throttle time to avoid frequent calls
|
||||
exhaustMapWithTrailing((present: boolean) => {
|
||||
return fromPromise(async () => {
|
||||
if (!this.aiButtonProvider) {
|
||||
return;
|
||||
}
|
||||
if (present) {
|
||||
await this.aiButtonProvider.presentAIButton();
|
||||
} else {
|
||||
await this.aiButtonProvider.dismissAIButton();
|
||||
}
|
||||
return;
|
||||
}).pipe(
|
||||
mergeMap(() => EMPTY),
|
||||
catchError(err => {
|
||||
logger.error('presentAIButton error', err);
|
||||
return EMPTY;
|
||||
})
|
||||
);
|
||||
})
|
||||
);
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import { configureQuotaModule } from '@affine/core/modules/quota';
|
||||
import { configureInfraModules, type Framework } from '@toeverything/infra';
|
||||
|
||||
import { configureAIButtonModule } from './ai-button';
|
||||
import { configureAppSidebarModule } from './app-sidebar';
|
||||
import { configureCloudModule } from './cloud';
|
||||
import { configureCollectionModule } from './collection';
|
||||
@ -67,4 +68,5 @@ export function configureCommonModules(framework: Framework) {
|
||||
configureDialogModule(framework);
|
||||
configureDocInfoModule(framework);
|
||||
configureOpenInApp(framework);
|
||||
configureAIButtonModule(framework);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user