refactor: move harmonyos project to harmony/ directory
This commit is contained in:
10
harmony/AppScope/app.json5
Normal file
10
harmony/AppScope/app.json5
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"app": {
|
||||
"bundleName": "com.trulymem.app",
|
||||
"vendor": "trulymem",
|
||||
"versionCode": 1000001,
|
||||
"versionName": "1.0.0",
|
||||
"icon": "$media:layered_image",
|
||||
"label": "$string:app_name"
|
||||
}
|
||||
}
|
||||
5
harmony/AppScope/resources/base/media/layered_image.svg
Normal file
5
harmony/AppScope/resources/base/media/layered_image.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">
|
||||
<rect width="200" height="200" rx="30" fill="#6366f1"/>
|
||||
<text x="100" y="130" font-family="Arial" font-size="80" fill="white" text-anchor="middle" font-weight="bold">T</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 313 B |
47
harmony/build-profile.json5
Normal file
47
harmony/build-profile.json5
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"app": {
|
||||
"products": [
|
||||
{
|
||||
"name": "default",
|
||||
"targetSdkVersion": "6.1.0(23)",
|
||||
"compatibleSdkVersion": "6.1.0(23)",
|
||||
"runtimeOS": "HarmonyOS",
|
||||
"buildOption": {
|
||||
"strictMode": {
|
||||
"caseSensitiveCheck": true,
|
||||
"useNormalizedOHMUrl": true
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildModeSet": [
|
||||
{
|
||||
"name": "debug"
|
||||
},
|
||||
{
|
||||
"name": "release"
|
||||
}
|
||||
]
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"name": "entry",
|
||||
"srcPath": "./entry",
|
||||
"targets": [
|
||||
{
|
||||
"name": "default",
|
||||
"applyToProducts": ["default"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "trulymem-core",
|
||||
"srcPath": "./trulymem-core",
|
||||
"targets": [
|
||||
{
|
||||
"name": "default"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
32
harmony/code-linter.json5
Normal file
32
harmony/code-linter.json5
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"files": [
|
||||
"**/*.ets"
|
||||
],
|
||||
"ignore": [
|
||||
"**/src/ohosTest/**/*",
|
||||
"**/src/test/**/*",
|
||||
"**/src/mock/**/*",
|
||||
"**/node_modules/**/*",
|
||||
"**/oh_modules/**/*",
|
||||
"**/build/**/*",
|
||||
"**/.preview/**/*"
|
||||
],
|
||||
"ruleSet": [
|
||||
"plugin:@performance/recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"@security/no-unsafe-aes": "error",
|
||||
"@security/no-unsafe-hash": "error",
|
||||
"@security/no-unsafe-mac": "warn",
|
||||
"@security/no-unsafe-dh": "error",
|
||||
"@security/no-unsafe-dsa": "error",
|
||||
"@security/no-unsafe-ecdsa": "error",
|
||||
"@security/no-unsafe-rsa-encrypt": "error",
|
||||
"@security/no-unsafe-rsa-sign": "error",
|
||||
"@security/no-unsafe-rsa-key": "error",
|
||||
"@security/no-unsafe-dsa-key": "error",
|
||||
"@security/no-unsafe-dh-key": "error",
|
||||
"@security/no-unsafe-3des": "error"
|
||||
}
|
||||
}
|
||||
38
harmony/entry/build-profile.json5
Normal file
38
harmony/entry/build-profile.json5
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"apiType": "stageMode",
|
||||
"buildOption": {
|
||||
"resOptions": {
|
||||
"copyCodeResource": {
|
||||
"enable": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"buildOptionSet": [
|
||||
{
|
||||
"name": "release",
|
||||
"arkOptions": {
|
||||
"obfuscation": {
|
||||
"ruleOptions": {
|
||||
"enable": true,
|
||||
"files": [
|
||||
"./obfuscation-rules.txt"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"resOptions": {
|
||||
"copyCodeResource": {
|
||||
"enable": false
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
"targets": [
|
||||
{
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"name": "ohosTest",
|
||||
}
|
||||
]
|
||||
}
|
||||
2176
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/.ts_checker_cache
vendored
Normal file
2176
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/.ts_checker_cache
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/.tsbuildinfo
vendored
Normal file
1
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/.tsbuildinfo
vendored
Normal file
File diff suppressed because one or more lines are too long
1
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/.tsbuildinfo.linter
vendored
Normal file
1
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/.tsbuildinfo.linter
vendored
Normal file
File diff suppressed because one or more lines are too long
1
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/compileInfo.json
vendored
Normal file
1
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/compileInfo.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"buildMode":"Debug"}
|
||||
@ -0,0 +1 @@
|
||||
{"hspPkgNames":[],"compileEntries":["&entry/build/generated/r/ResourceTable&","&entry/src/main/ets/entryability/EntryAbility&","&entry/src/main/ets/pages/Index&"],"updateVersionInfo":{}}
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@
|
||||
<EFBFBD>r@<40>
|
||||
Binary file not shown.
1
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/dep_info.json
vendored
Normal file
1
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/dep_info.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"resolveConflictMode":true}
|
||||
@ -0,0 +1,2 @@
|
||||
"use strict";
|
||||
//# sourceMappingURL=ResourceTable.js.map
|
||||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,30 @@
|
||||
import type AbilityConstant from "@ohos:app.ability.AbilityConstant";
|
||||
import UIAbility from "@ohos:app.ability.UIAbility";
|
||||
import type Window from "@ohos:window";
|
||||
import type Want from "@ohos:app.ability.Want";
|
||||
export default class EntryAbility extends UIAbility {
|
||||
onCreate(want: Want, param: AbilityConstant.LaunchParam): void {
|
||||
console.info('EntryAbility onCreate');
|
||||
}
|
||||
onDestroy(): void {
|
||||
console.info('EntryAbility onDestroy');
|
||||
}
|
||||
onWindowStageCreate(windowStage: Window.WindowStage): void {
|
||||
windowStage.loadContent('pages/Index', (err, data) => {
|
||||
if (err.code) {
|
||||
console.error('Failed to load content: ' + JSON.stringify(err));
|
||||
return;
|
||||
}
|
||||
console.info('Succeeded in loading content: ' + JSON.stringify(data));
|
||||
});
|
||||
}
|
||||
onWindowStageDestroy(): void {
|
||||
console.info('EntryAbility onWindowStageDestroy');
|
||||
}
|
||||
onForeground(): void {
|
||||
console.info('EntryAbility onForeground');
|
||||
}
|
||||
onBackground(): void {
|
||||
console.info('EntryAbility onBackground');
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@ -0,0 +1,222 @@
|
||||
import relationalStore from "@ohos:data.relationalStore";
|
||||
import type { Context } from "@ohos:abilityAccessCtrl";
|
||||
interface TripletData {
|
||||
subject: string;
|
||||
relation: string;
|
||||
object: string;
|
||||
}
|
||||
interface CriteriaData {
|
||||
subject?: string;
|
||||
target?: string;
|
||||
relation?: string;
|
||||
sessionId?: string;
|
||||
}
|
||||
interface NodeData {
|
||||
id: number;
|
||||
label: string;
|
||||
type: string;
|
||||
mentions: number;
|
||||
}
|
||||
interface EdgeData {
|
||||
from: number;
|
||||
to: number;
|
||||
label: string;
|
||||
weight: number;
|
||||
}
|
||||
interface GraphData {
|
||||
nodes: NodeData[];
|
||||
edges: EdgeData[];
|
||||
}
|
||||
interface RecallResult {
|
||||
data: GraphData;
|
||||
}
|
||||
interface ChatMessage {
|
||||
role: string;
|
||||
content: string;
|
||||
}
|
||||
interface CleanupResult {
|
||||
cleaned: number;
|
||||
}
|
||||
const STORE_CONFIG: relationalStore.StoreConfig = {
|
||||
name: 'trulymem.db',
|
||||
securityLevel: relationalStore.SecurityLevel.S1
|
||||
};
|
||||
export class GraphDatabase {
|
||||
private store?: relationalStore.RdbStore;
|
||||
private context?: Context;
|
||||
async init(context: Context): Promise<void> {
|
||||
this.context = context;
|
||||
this.store = await relationalStore.getRdbStore(context, STORE_CONFIG);
|
||||
await this.createTables();
|
||||
}
|
||||
private async createTables(): Promise<void> {
|
||||
if (!this.store)
|
||||
return;
|
||||
await this.store.executeSql(`
|
||||
CREATE TABLE IF NOT EXISTS nodes (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
type TEXT DEFAULT 'concept',
|
||||
mentions INTEGER DEFAULT 1,
|
||||
created_at TEXT,
|
||||
updated_at TEXT
|
||||
)
|
||||
`);
|
||||
await this.store.executeSql(`
|
||||
CREATE TABLE IF NOT EXISTS relations (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
subject_id INTEGER NOT NULL,
|
||||
relation TEXT NOT NULL,
|
||||
object_id INTEGER NOT NULL,
|
||||
weight REAL DEFAULT 1.0,
|
||||
created_at TEXT
|
||||
)
|
||||
`);
|
||||
await this.store.executeSql(`
|
||||
CREATE TABLE IF NOT EXISTS chat_records (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
role TEXT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
tools TEXT,
|
||||
created_at TEXT
|
||||
)
|
||||
`);
|
||||
}
|
||||
async commit(triplets: TripletData[]): Promise<void> {
|
||||
if (!this.store)
|
||||
return;
|
||||
for (const triplet of triplets) {
|
||||
const subjectId: number = await this.upsertNode(triplet.subject);
|
||||
const objectId: number = await this.upsertNode(triplet.object);
|
||||
const bucket: relationalStore.ValuesBucket = {
|
||||
'subject_id': subjectId,
|
||||
'relation': triplet.relation,
|
||||
'object_id': objectId,
|
||||
'created_at': new Date().toISOString()
|
||||
};
|
||||
await this.store.insert('relations', bucket);
|
||||
}
|
||||
}
|
||||
private async upsertNode(name: string): Promise<number> {
|
||||
if (!this.store)
|
||||
return -1;
|
||||
const predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('nodes');
|
||||
predicates.equalTo('name', name);
|
||||
const resultSet: relationalStore.ResultSet = await this.store.query(predicates, ['id']);
|
||||
if (resultSet.goToNextRow()) {
|
||||
const id: number = resultSet.getLong(resultSet.getColumnIndex('id'));
|
||||
resultSet.close();
|
||||
return id;
|
||||
}
|
||||
resultSet.close();
|
||||
const bucket: relationalStore.ValuesBucket = {
|
||||
'name': name,
|
||||
'type': 'concept',
|
||||
'created_at': new Date().toISOString(),
|
||||
'updated_at': new Date().toISOString()
|
||||
};
|
||||
return await this.store.insert('nodes', bucket);
|
||||
}
|
||||
async recall(queryIntent: string, seedEntities?: string[]): Promise<RecallResult> {
|
||||
if (!this.store) {
|
||||
const empty: RecallResult = { data: { nodes: [], edges: [] } };
|
||||
return empty;
|
||||
}
|
||||
const nodes: NodeData[] = await this.getAllNodes();
|
||||
const edges: EdgeData[] = await this.getAllEdges();
|
||||
const result: RecallResult = { data: { nodes, edges } };
|
||||
return result;
|
||||
}
|
||||
async purge(criteria: CriteriaData): Promise<void> {
|
||||
if (!this.store)
|
||||
return;
|
||||
const predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('nodes');
|
||||
await this.store.delete(predicates);
|
||||
}
|
||||
async introspect(): Promise<RecallResult> {
|
||||
const nodes: NodeData[] = await this.getAllNodes();
|
||||
const edges: EdgeData[] = await this.getAllEdges();
|
||||
const result: RecallResult = { data: { nodes, edges } };
|
||||
return result;
|
||||
}
|
||||
async archive(days: number): Promise<void> {
|
||||
// Archive old data - placeholder
|
||||
}
|
||||
async cleanup(dryRun: boolean): Promise<CleanupResult> {
|
||||
const result: CleanupResult = { cleaned: 0 };
|
||||
return result;
|
||||
}
|
||||
async saveChatMessage(role: string, content: string, tools?: string): Promise<void> {
|
||||
if (!this.store)
|
||||
return;
|
||||
const bucket: relationalStore.ValuesBucket = {
|
||||
'role': role,
|
||||
'content': content,
|
||||
'tools': tools || null,
|
||||
'created_at': new Date().toISOString()
|
||||
};
|
||||
await this.store.insert('chat_records', bucket);
|
||||
}
|
||||
async getChatHistory(limit?: number): Promise<ChatMessage[]> {
|
||||
if (!this.store)
|
||||
return [];
|
||||
const predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('chat_records');
|
||||
predicates.orderByDesc('created_at');
|
||||
if (limit) {
|
||||
predicates.limitAs(limit);
|
||||
}
|
||||
const resultSet: relationalStore.ResultSet = await this.store.query(predicates, ['role', 'content']);
|
||||
const messages: ChatMessage[] = [];
|
||||
while (resultSet.goToNextRow()) {
|
||||
const msg: ChatMessage = {
|
||||
role: resultSet.getString(resultSet.getColumnIndex('role')),
|
||||
content: resultSet.getString(resultSet.getColumnIndex('content'))
|
||||
};
|
||||
messages.push(msg);
|
||||
}
|
||||
resultSet.close();
|
||||
return messages.reverse();
|
||||
}
|
||||
async clearChatHistory(): Promise<void> {
|
||||
if (!this.store)
|
||||
return;
|
||||
const predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('chat_records');
|
||||
await this.store.delete(predicates);
|
||||
}
|
||||
private async getAllNodes(): Promise<NodeData[]> {
|
||||
if (!this.store)
|
||||
return [];
|
||||
const predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('nodes');
|
||||
const resultSet: relationalStore.ResultSet = await this.store.query(predicates, ['id', 'name', 'type', 'mentions']);
|
||||
const nodes: NodeData[] = [];
|
||||
while (resultSet.goToNextRow()) {
|
||||
const node: NodeData = {
|
||||
id: resultSet.getLong(resultSet.getColumnIndex('id')),
|
||||
label: resultSet.getString(resultSet.getColumnIndex('name')),
|
||||
type: resultSet.getString(resultSet.getColumnIndex('type')),
|
||||
mentions: resultSet.getLong(resultSet.getColumnIndex('mentions'))
|
||||
};
|
||||
nodes.push(node);
|
||||
}
|
||||
resultSet.close();
|
||||
return nodes;
|
||||
}
|
||||
private async getAllEdges(): Promise<EdgeData[]> {
|
||||
if (!this.store)
|
||||
return [];
|
||||
const predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('relations');
|
||||
const resultSet: relationalStore.ResultSet = await this.store.query(predicates, ['subject_id', 'relation', 'object_id', 'weight']);
|
||||
const edges: EdgeData[] = [];
|
||||
while (resultSet.goToNextRow()) {
|
||||
const edge: EdgeData = {
|
||||
from: resultSet.getLong(resultSet.getColumnIndex('subject_id')),
|
||||
to: resultSet.getLong(resultSet.getColumnIndex('object_id')),
|
||||
label: resultSet.getString(resultSet.getColumnIndex('relation')),
|
||||
weight: resultSet.getDouble(resultSet.getColumnIndex('weight'))
|
||||
};
|
||||
edges.push(edge);
|
||||
}
|
||||
resultSet.close();
|
||||
return edges;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@ -0,0 +1,205 @@
|
||||
if (!("finalizeConstruction" in ViewPU.prototype)) {
|
||||
Reflect.set(ViewPU.prototype, "finalizeConstruction", () => { });
|
||||
}
|
||||
interface ChatPage_Params {
|
||||
messages?: ChatMessage[];
|
||||
inputText?: string;
|
||||
db?: GraphDatabase;
|
||||
scrollController?: Scroller;
|
||||
}
|
||||
import http from "@ohos:net.http";
|
||||
import dataPreferences from "@ohos:data.preferences";
|
||||
import type { GraphDatabase } from '../model/GraphDatabase';
|
||||
interface ChatMessage {
|
||||
role: string;
|
||||
content: string;
|
||||
}
|
||||
export class ChatPage extends ViewPU {
|
||||
constructor(parent, params, __localStorage, elmtId = -1, paramsLambda = undefined, extraInfo) {
|
||||
super(parent, __localStorage, elmtId, extraInfo);
|
||||
if (typeof paramsLambda === "function") {
|
||||
this.paramsGenerator_ = paramsLambda;
|
||||
}
|
||||
this.__messages = new ObservedPropertyObjectPU([], this, "messages");
|
||||
this.__inputText = new ObservedPropertySimplePU('', this, "inputText");
|
||||
this.__db = new SynchedPropertyObjectOneWayPU(params.db, this, "db");
|
||||
this.scrollController = new Scroller();
|
||||
this.setInitiallyProvidedValue(params);
|
||||
this.finalizeConstruction();
|
||||
}
|
||||
setInitiallyProvidedValue(params: ChatPage_Params) {
|
||||
if (params.messages !== undefined) {
|
||||
this.messages = params.messages;
|
||||
}
|
||||
if (params.inputText !== undefined) {
|
||||
this.inputText = params.inputText;
|
||||
}
|
||||
if (params.scrollController !== undefined) {
|
||||
this.scrollController = params.scrollController;
|
||||
}
|
||||
}
|
||||
updateStateVars(params: ChatPage_Params) {
|
||||
this.__db.reset(params.db);
|
||||
}
|
||||
purgeVariableDependenciesOnElmtId(rmElmtId) {
|
||||
this.__messages.purgeDependencyOnElmtId(rmElmtId);
|
||||
this.__inputText.purgeDependencyOnElmtId(rmElmtId);
|
||||
this.__db.purgeDependencyOnElmtId(rmElmtId);
|
||||
}
|
||||
aboutToBeDeleted() {
|
||||
this.__messages.aboutToBeDeleted();
|
||||
this.__inputText.aboutToBeDeleted();
|
||||
this.__db.aboutToBeDeleted();
|
||||
SubscriberManager.Get().delete(this.id__());
|
||||
this.aboutToBeDeletedInternal();
|
||||
}
|
||||
private __messages: ObservedPropertyObjectPU<ChatMessage[]>;
|
||||
get messages() {
|
||||
return this.__messages.get();
|
||||
}
|
||||
set messages(newValue: ChatMessage[]) {
|
||||
this.__messages.set(newValue);
|
||||
}
|
||||
private __inputText: ObservedPropertySimplePU<string>;
|
||||
get inputText() {
|
||||
return this.__inputText.get();
|
||||
}
|
||||
set inputText(newValue: string) {
|
||||
this.__inputText.set(newValue);
|
||||
}
|
||||
private __db: SynchedPropertySimpleOneWayPU<GraphDatabase>;
|
||||
get db() {
|
||||
return this.__db.get();
|
||||
}
|
||||
set db(newValue: GraphDatabase) {
|
||||
this.__db.set(newValue);
|
||||
}
|
||||
private scrollController: Scroller;
|
||||
async aboutToAppear() {
|
||||
this.messages = await this.db.getChatHistory(50);
|
||||
}
|
||||
async sendMessage() {
|
||||
if (!this.inputText.trim())
|
||||
return;
|
||||
const userMessage: string = this.inputText;
|
||||
this.inputText = '';
|
||||
await this.db.saveChatMessage('user', userMessage);
|
||||
const userMsg: ChatMessage = { role: 'user', content: userMessage };
|
||||
this.messages = [...this.messages, userMsg];
|
||||
const pref: dataPreferences.Preferences = await dataPreferences.getPreferences(getContext(this), 'trulymem_config');
|
||||
const baseUrl: string = String(await pref.get('base_url', 'https://api.deepseek.com'));
|
||||
const model: string = String(await pref.get('model', 'deepseek-chat'));
|
||||
const apiKey: string = String(await pref.get('api_key', ''));
|
||||
try {
|
||||
const httpRequest: http.HttpRequest = http.createHttp();
|
||||
const response: http.HttpResponse = await httpRequest.request(baseUrl + '/chat/completions', {
|
||||
method: http.RequestMethod.POST,
|
||||
header: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + apiKey
|
||||
},
|
||||
extraData: {
|
||||
model: model,
|
||||
messages: [{ role: 'user', content: userMessage }]
|
||||
}
|
||||
});
|
||||
if (response.responseCode === 200) {
|
||||
const data: object = JSON.parse(String(response.result));
|
||||
const choicesArr: object[] = data['choices'] as object[];
|
||||
if (choicesArr && choicesArr.length > 0) {
|
||||
const firstChoice: object = choicesArr[0];
|
||||
const msgObj: object = firstChoice['message'] as object;
|
||||
const assistantMessage: string = String(msgObj['content']);
|
||||
await this.db.saveChatMessage('assistant', assistantMessage);
|
||||
const aiMsg: ChatMessage = { role: 'assistant', content: assistantMessage };
|
||||
this.messages = [...this.messages, aiMsg];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
console.error('HTTP request failed: ' + JSON.stringify(err));
|
||||
}
|
||||
}
|
||||
initialRender() {
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
Column.create();
|
||||
Column.width('100%');
|
||||
Column.height('100%');
|
||||
}, Column);
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
List.create();
|
||||
List.width('100%');
|
||||
List.layoutWeight(1);
|
||||
}, List);
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
ForEach.create();
|
||||
const forEachItemGenFunction = _item => {
|
||||
const msg = _item;
|
||||
{
|
||||
const itemCreation = (elmtId, isInitialRender) => {
|
||||
ViewStackProcessor.StartGetAccessRecordingFor(elmtId);
|
||||
ListItem.create(deepRenderFunction, true);
|
||||
if (!isInitialRender) {
|
||||
ListItem.pop();
|
||||
}
|
||||
ViewStackProcessor.StopGetAccessRecording();
|
||||
};
|
||||
const itemCreation2 = (elmtId, isInitialRender) => {
|
||||
ListItem.create(deepRenderFunction, true);
|
||||
};
|
||||
const deepRenderFunction = (elmtId, isInitialRender) => {
|
||||
itemCreation(elmtId, isInitialRender);
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
Column.create();
|
||||
Column.padding(12);
|
||||
Column.backgroundColor(msg.role === 'user' ? '#E3F2FD' : '#F5F5F5');
|
||||
Column.borderRadius(8);
|
||||
Column.margin({ left: 8, right: 8, bottom: 8 });
|
||||
}, Column);
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
Text.create(msg.role);
|
||||
Text.fontSize(12);
|
||||
Text.fontColor('#666');
|
||||
Text.width('100%');
|
||||
}, Text);
|
||||
Text.pop();
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
Text.create(msg.content);
|
||||
Text.fontSize(16);
|
||||
Text.width('100%');
|
||||
Text.margin({ top: 4 });
|
||||
}, Text);
|
||||
Text.pop();
|
||||
Column.pop();
|
||||
ListItem.pop();
|
||||
};
|
||||
this.observeComponentCreation2(itemCreation2, ListItem);
|
||||
ListItem.pop();
|
||||
}
|
||||
};
|
||||
this.forEachUpdateFunction(elmtId, this.messages, forEachItemGenFunction);
|
||||
}, ForEach);
|
||||
ForEach.pop();
|
||||
List.pop();
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
Row.create();
|
||||
Row.width('100%');
|
||||
Row.padding(8);
|
||||
}, Row);
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
TextArea.create({ text: this.inputText, placeholder: '输入消息...' });
|
||||
TextArea.layoutWeight(1);
|
||||
TextArea.onChange((v: string) => { this.inputText = v; });
|
||||
}, TextArea);
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
Button.createWithLabel('发送');
|
||||
Button.onClick(() => this.sendMessage());
|
||||
}, Button);
|
||||
Button.pop();
|
||||
Row.pop();
|
||||
Column.pop();
|
||||
}
|
||||
rerender() {
|
||||
this.updateDirtyElements();
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@ -0,0 +1,65 @@
|
||||
if (!("finalizeConstruction" in ViewPU.prototype)) {
|
||||
Reflect.set(ViewPU.prototype, "finalizeConstruction", () => { });
|
||||
}
|
||||
interface GraphPage_Params {
|
||||
controller?: web_webview.WebviewController;
|
||||
db?: GraphDatabase;
|
||||
}
|
||||
import web_webview from "@ohos:web.webview";
|
||||
import type { GraphDatabase } from '../model/GraphDatabase';
|
||||
export class GraphPage extends ViewPU {
|
||||
constructor(parent, params, __localStorage, elmtId = -1, paramsLambda = undefined, extraInfo) {
|
||||
super(parent, __localStorage, elmtId, extraInfo);
|
||||
if (typeof paramsLambda === "function") {
|
||||
this.paramsGenerator_ = paramsLambda;
|
||||
}
|
||||
this.controller = new web_webview.WebviewController();
|
||||
this.__db = new SynchedPropertyObjectOneWayPU(params.db, this, "db");
|
||||
this.setInitiallyProvidedValue(params);
|
||||
this.finalizeConstruction();
|
||||
}
|
||||
setInitiallyProvidedValue(params: GraphPage_Params) {
|
||||
if (params.controller !== undefined) {
|
||||
this.controller = params.controller;
|
||||
}
|
||||
}
|
||||
updateStateVars(params: GraphPage_Params) {
|
||||
this.__db.reset(params.db);
|
||||
}
|
||||
purgeVariableDependenciesOnElmtId(rmElmtId) {
|
||||
this.__db.purgeDependencyOnElmtId(rmElmtId);
|
||||
}
|
||||
aboutToBeDeleted() {
|
||||
this.__db.aboutToBeDeleted();
|
||||
SubscriberManager.Get().delete(this.id__());
|
||||
this.aboutToBeDeletedInternal();
|
||||
}
|
||||
private controller: web_webview.WebviewController;
|
||||
private __db: SynchedPropertySimpleOneWayPU<GraphDatabase>;
|
||||
get db() {
|
||||
return this.__db.get();
|
||||
}
|
||||
set db(newValue: GraphDatabase) {
|
||||
this.__db.set(newValue);
|
||||
}
|
||||
initialRender() {
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
Column.create();
|
||||
Column.width('100%');
|
||||
Column.height('100%');
|
||||
Column.onAppear(() => {
|
||||
this.controller.refresh();
|
||||
});
|
||||
}, Column);
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
Web.create({ src: { "id": 0, "type": 30000, params: ['graph.html'], "bundleName": "com.trulymem.app", "moduleName": "entry" }, controller: this.controller });
|
||||
Web.javaScriptAccess(true);
|
||||
Web.width('100%');
|
||||
Web.height('100%');
|
||||
}, Web);
|
||||
Column.pop();
|
||||
}
|
||||
rerender() {
|
||||
this.updateDirtyElements();
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@ -0,0 +1,119 @@
|
||||
if (!("finalizeConstruction" in ViewPU.prototype)) {
|
||||
Reflect.set(ViewPU.prototype, "finalizeConstruction", () => { });
|
||||
}
|
||||
interface Index_Params {
|
||||
currentIndex?: number;
|
||||
db?: GraphDatabase;
|
||||
}
|
||||
import { MainPage } from "@normalized:N&&&entry/src/main/ets/pages/MainPage&";
|
||||
import { SettingsPage } from "@normalized:N&&&entry/src/main/ets/pages/SettingsPage&";
|
||||
import { GraphDatabase } from "@normalized:N&&&entry/src/main/ets/model/GraphDatabase&";
|
||||
class Index extends ViewPU {
|
||||
constructor(parent, params, __localStorage, elmtId = -1, paramsLambda = undefined, extraInfo) {
|
||||
super(parent, __localStorage, elmtId, extraInfo);
|
||||
if (typeof paramsLambda === "function") {
|
||||
this.paramsGenerator_ = paramsLambda;
|
||||
}
|
||||
this.__currentIndex = new ObservedPropertySimplePU(0, this, "currentIndex");
|
||||
this.db = new GraphDatabase();
|
||||
this.setInitiallyProvidedValue(params);
|
||||
this.finalizeConstruction();
|
||||
}
|
||||
setInitiallyProvidedValue(params: Index_Params) {
|
||||
if (params.currentIndex !== undefined) {
|
||||
this.currentIndex = params.currentIndex;
|
||||
}
|
||||
if (params.db !== undefined) {
|
||||
this.db = params.db;
|
||||
}
|
||||
}
|
||||
updateStateVars(params: Index_Params) {
|
||||
}
|
||||
purgeVariableDependenciesOnElmtId(rmElmtId) {
|
||||
this.__currentIndex.purgeDependencyOnElmtId(rmElmtId);
|
||||
}
|
||||
aboutToBeDeleted() {
|
||||
this.__currentIndex.aboutToBeDeleted();
|
||||
SubscriberManager.Get().delete(this.id__());
|
||||
this.aboutToBeDeletedInternal();
|
||||
}
|
||||
private __currentIndex: ObservedPropertySimplePU<number>;
|
||||
get currentIndex() {
|
||||
return this.__currentIndex.get();
|
||||
}
|
||||
set currentIndex(newValue: number) {
|
||||
this.__currentIndex.set(newValue);
|
||||
}
|
||||
private db: GraphDatabase;
|
||||
aboutToAppear() {
|
||||
this.db.init(getContext(this));
|
||||
}
|
||||
initialRender() {
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
Column.create();
|
||||
Column.width('100%');
|
||||
Column.height('100%');
|
||||
}, Column);
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
Tabs.create({ index: this.currentIndex, barPosition: BarPosition.End });
|
||||
Tabs.width('100%');
|
||||
Tabs.height('100%');
|
||||
Tabs.onChange((index: number) => { this.currentIndex = index; });
|
||||
}, Tabs);
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
TabContent.create(() => {
|
||||
{
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
if (isInitialRender) {
|
||||
let componentCall = new MainPage(this, { db: this.db }, undefined, elmtId, () => { }, { page: "entry/src/main/ets/pages/Index.ets", line: 19, col: 21 });
|
||||
ViewPU.create(componentCall);
|
||||
let paramsLambda = () => {
|
||||
return {
|
||||
db: this.db
|
||||
};
|
||||
};
|
||||
componentCall.paramsGenerator_ = paramsLambda;
|
||||
}
|
||||
else {
|
||||
this.updateStateVarsOfChildByElmtId(elmtId, {
|
||||
db: this.db
|
||||
});
|
||||
}
|
||||
}, { name: "MainPage" });
|
||||
}
|
||||
});
|
||||
TabContent.tabBar('🌌 TrulyMEM');
|
||||
}, TabContent);
|
||||
TabContent.pop();
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
TabContent.create(() => {
|
||||
{
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
if (isInitialRender) {
|
||||
let componentCall = new SettingsPage(this, {}, undefined, elmtId, () => { }, { page: "entry/src/main/ets/pages/Index.ets", line: 24, col: 21 });
|
||||
ViewPU.create(componentCall);
|
||||
let paramsLambda = () => {
|
||||
return {};
|
||||
};
|
||||
componentCall.paramsGenerator_ = paramsLambda;
|
||||
}
|
||||
else {
|
||||
this.updateStateVarsOfChildByElmtId(elmtId, {});
|
||||
}
|
||||
}, { name: "SettingsPage" });
|
||||
}
|
||||
});
|
||||
TabContent.tabBar('⚙ 设置');
|
||||
}, TabContent);
|
||||
TabContent.pop();
|
||||
Tabs.pop();
|
||||
Column.pop();
|
||||
}
|
||||
rerender() {
|
||||
this.updateDirtyElements();
|
||||
}
|
||||
static getEntryName(): string {
|
||||
return "Index";
|
||||
}
|
||||
}
|
||||
registerNamedRoute(() => new Index(undefined, {}), "", { bundleName: "com.trulymem.app", moduleName: "entry", pagePath: "pages/Index", pageFullPath: "entry/src/main/ets/pages/Index", integratedHsp: "false", moduleType: "followWithHap" });
|
||||
Binary file not shown.
@ -0,0 +1,97 @@
|
||||
if (!("finalizeConstruction" in ViewPU.prototype)) {
|
||||
Reflect.set(ViewPU.prototype, "finalizeConstruction", () => { });
|
||||
}
|
||||
interface MainPage_Params {
|
||||
db?: GraphDatabase;
|
||||
}
|
||||
import type { GraphDatabase } from '../model/GraphDatabase';
|
||||
import { GraphPage } from "@normalized:N&&&entry/src/main/ets/pages/GraphPage&";
|
||||
import { ChatPage } from "@normalized:N&&&entry/src/main/ets/pages/ChatPage&";
|
||||
export class MainPage extends ViewPU {
|
||||
constructor(parent, params, __localStorage, elmtId = -1, paramsLambda = undefined, extraInfo) {
|
||||
super(parent, __localStorage, elmtId, extraInfo);
|
||||
if (typeof paramsLambda === "function") {
|
||||
this.paramsGenerator_ = paramsLambda;
|
||||
}
|
||||
this.__db = new SynchedPropertyObjectOneWayPU(params.db, this, "db");
|
||||
this.setInitiallyProvidedValue(params);
|
||||
this.finalizeConstruction();
|
||||
}
|
||||
setInitiallyProvidedValue(params: MainPage_Params) {
|
||||
}
|
||||
updateStateVars(params: MainPage_Params) {
|
||||
this.__db.reset(params.db);
|
||||
}
|
||||
purgeVariableDependenciesOnElmtId(rmElmtId) {
|
||||
this.__db.purgeDependencyOnElmtId(rmElmtId);
|
||||
}
|
||||
aboutToBeDeleted() {
|
||||
this.__db.aboutToBeDeleted();
|
||||
SubscriberManager.Get().delete(this.id__());
|
||||
this.aboutToBeDeletedInternal();
|
||||
}
|
||||
private __db: SynchedPropertySimpleOneWayPU<GraphDatabase>;
|
||||
get db() {
|
||||
return this.__db.get();
|
||||
}
|
||||
set db(newValue: GraphDatabase) {
|
||||
this.__db.set(newValue);
|
||||
}
|
||||
initialRender() {
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
GridRow.create({ columns: { sm: 1, md: 2, lg: 2 }, gutter: { x: 8, y: 8 } });
|
||||
GridRow.width('100%');
|
||||
GridRow.height('100%');
|
||||
}, GridRow);
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
GridCol.create({ span: { sm: 1, md: 1, lg: 1 } });
|
||||
}, GridCol);
|
||||
{
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
if (isInitialRender) {
|
||||
let componentCall = new GraphPage(this, { db: this.db }, undefined, elmtId, () => { }, { page: "entry/src/main/ets/pages/MainPage.ets", line: 12, col: 17 });
|
||||
ViewPU.create(componentCall);
|
||||
let paramsLambda = () => {
|
||||
return {
|
||||
db: this.db
|
||||
};
|
||||
};
|
||||
componentCall.paramsGenerator_ = paramsLambda;
|
||||
}
|
||||
else {
|
||||
this.updateStateVarsOfChildByElmtId(elmtId, {
|
||||
db: this.db
|
||||
});
|
||||
}
|
||||
}, { name: "GraphPage" });
|
||||
}
|
||||
GridCol.pop();
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
GridCol.create({ span: { sm: 1, md: 1, lg: 1 } });
|
||||
}, GridCol);
|
||||
{
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
if (isInitialRender) {
|
||||
let componentCall = new ChatPage(this, { db: this.db }, undefined, elmtId, () => { }, { page: "entry/src/main/ets/pages/MainPage.ets", line: 15, col: 17 });
|
||||
ViewPU.create(componentCall);
|
||||
let paramsLambda = () => {
|
||||
return {
|
||||
db: this.db
|
||||
};
|
||||
};
|
||||
componentCall.paramsGenerator_ = paramsLambda;
|
||||
}
|
||||
else {
|
||||
this.updateStateVarsOfChildByElmtId(elmtId, {
|
||||
db: this.db
|
||||
});
|
||||
}
|
||||
}, { name: "ChatPage" });
|
||||
}
|
||||
GridCol.pop();
|
||||
GridRow.pop();
|
||||
}
|
||||
rerender() {
|
||||
this.updateDirtyElements();
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@ -0,0 +1,152 @@
|
||||
if (!("finalizeConstruction" in ViewPU.prototype)) {
|
||||
Reflect.set(ViewPU.prototype, "finalizeConstruction", () => { });
|
||||
}
|
||||
interface SettingsPage_Params {
|
||||
baseUrl?: string;
|
||||
model?: string;
|
||||
apiKey?: string;
|
||||
pref?: dataPreferences.Preferences;
|
||||
}
|
||||
import dataPreferences from "@ohos:data.preferences";
|
||||
export class SettingsPage extends ViewPU {
|
||||
constructor(parent, params, __localStorage, elmtId = -1, paramsLambda = undefined, extraInfo) {
|
||||
super(parent, __localStorage, elmtId, extraInfo);
|
||||
if (typeof paramsLambda === "function") {
|
||||
this.paramsGenerator_ = paramsLambda;
|
||||
}
|
||||
this.__baseUrl = new ObservedPropertySimplePU('', this, "baseUrl");
|
||||
this.__model = new ObservedPropertySimplePU('', this, "model");
|
||||
this.__apiKey = new ObservedPropertySimplePU('', this, "apiKey");
|
||||
this.pref = undefined;
|
||||
this.setInitiallyProvidedValue(params);
|
||||
this.finalizeConstruction();
|
||||
}
|
||||
setInitiallyProvidedValue(params: SettingsPage_Params) {
|
||||
if (params.baseUrl !== undefined) {
|
||||
this.baseUrl = params.baseUrl;
|
||||
}
|
||||
if (params.model !== undefined) {
|
||||
this.model = params.model;
|
||||
}
|
||||
if (params.apiKey !== undefined) {
|
||||
this.apiKey = params.apiKey;
|
||||
}
|
||||
if (params.pref !== undefined) {
|
||||
this.pref = params.pref;
|
||||
}
|
||||
}
|
||||
updateStateVars(params: SettingsPage_Params) {
|
||||
}
|
||||
purgeVariableDependenciesOnElmtId(rmElmtId) {
|
||||
this.__baseUrl.purgeDependencyOnElmtId(rmElmtId);
|
||||
this.__model.purgeDependencyOnElmtId(rmElmtId);
|
||||
this.__apiKey.purgeDependencyOnElmtId(rmElmtId);
|
||||
}
|
||||
aboutToBeDeleted() {
|
||||
this.__baseUrl.aboutToBeDeleted();
|
||||
this.__model.aboutToBeDeleted();
|
||||
this.__apiKey.aboutToBeDeleted();
|
||||
SubscriberManager.Get().delete(this.id__());
|
||||
this.aboutToBeDeletedInternal();
|
||||
}
|
||||
private __baseUrl: ObservedPropertySimplePU<string>;
|
||||
get baseUrl() {
|
||||
return this.__baseUrl.get();
|
||||
}
|
||||
set baseUrl(newValue: string) {
|
||||
this.__baseUrl.set(newValue);
|
||||
}
|
||||
private __model: ObservedPropertySimplePU<string>;
|
||||
get model() {
|
||||
return this.__model.get();
|
||||
}
|
||||
set model(newValue: string) {
|
||||
this.__model.set(newValue);
|
||||
}
|
||||
private __apiKey: ObservedPropertySimplePU<string>;
|
||||
get apiKey() {
|
||||
return this.__apiKey.get();
|
||||
}
|
||||
set apiKey(newValue: string) {
|
||||
this.__apiKey.set(newValue);
|
||||
}
|
||||
private pref?: dataPreferences.Preferences;
|
||||
async aboutToAppear() {
|
||||
const ctx = getContext(this);
|
||||
this.pref = await dataPreferences.getPreferences(ctx, 'trulymem_config');
|
||||
this.baseUrl = String(await this.pref.get('base_url', 'https://api.deepseek.com'));
|
||||
this.model = String(await this.pref.get('model', 'deepseek-chat'));
|
||||
this.apiKey = String(await this.pref.get('api_key', ''));
|
||||
}
|
||||
async onBaseUrlChange(value: string) {
|
||||
this.baseUrl = value;
|
||||
await this.pref?.put('base_url', value);
|
||||
await this.pref?.flush();
|
||||
}
|
||||
async onModelChange(value: string) {
|
||||
this.model = value;
|
||||
await this.pref?.put('model', value);
|
||||
await this.pref?.flush();
|
||||
}
|
||||
async onApiKeyChange(value: string) {
|
||||
this.apiKey = value;
|
||||
await this.pref?.put('api_key', value);
|
||||
await this.pref?.flush();
|
||||
}
|
||||
initialRender() {
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
Column.create();
|
||||
Column.width('100%');
|
||||
Column.height('100%');
|
||||
Column.padding(16);
|
||||
}, Column);
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
Text.create('API 配置');
|
||||
Text.fontSize(24);
|
||||
Text.fontWeight(FontWeight.Bold);
|
||||
Text.margin({ top: 20, bottom: 16 });
|
||||
}, Text);
|
||||
Text.pop();
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
Text.create('Base URL');
|
||||
Text.fontSize(14);
|
||||
Text.width('100%');
|
||||
Text.margin({ left: 16 });
|
||||
}, Text);
|
||||
Text.pop();
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
TextInput.create({ placeholder: 'https://api.deepseek.com', text: this.baseUrl });
|
||||
TextInput.onChange((v: string) => { this.onBaseUrlChange(v); });
|
||||
TextInput.margin({ left: 16, right: 16, bottom: 12 });
|
||||
}, TextInput);
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
Text.create('Model ID');
|
||||
Text.fontSize(14);
|
||||
Text.width('100%');
|
||||
Text.margin({ left: 16 });
|
||||
}, Text);
|
||||
Text.pop();
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
TextInput.create({ placeholder: 'deepseek-chat', text: this.model });
|
||||
TextInput.onChange((v: string) => { this.onModelChange(v); });
|
||||
TextInput.margin({ left: 16, right: 16, bottom: 12 });
|
||||
}, TextInput);
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
Text.create('API Key');
|
||||
Text.fontSize(14);
|
||||
Text.width('100%');
|
||||
Text.margin({ left: 16 });
|
||||
}, Text);
|
||||
Text.pop();
|
||||
this.observeComponentCreation2((elmtId, isInitialRender) => {
|
||||
TextInput.create({ placeholder: 'sk-...', text: this.apiKey });
|
||||
TextInput.type(InputType.Password);
|
||||
TextInput.onChange((v: string) => { this.onApiKeyChange(v); });
|
||||
TextInput.margin({ left: 16, right: 16, bottom: 12 });
|
||||
}, TextInput);
|
||||
Column.pop();
|
||||
}
|
||||
rerender() {
|
||||
this.updateDirtyElements();
|
||||
}
|
||||
}
|
||||
8
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/filesInfo.txt
vendored
Normal file
8
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/filesInfo.txt
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/build/default/generated/r/default/ResourceTable.js;&entry/build/generated/r/ResourceTable&;esm;entry|entry|1.0.0|build/default/generated/r/default/ResourceTable.js;entry;false;ts
|
||||
/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/entryability/EntryAbility.ts;&entry/src/main/ets/entryability/EntryAbility&;esm;entry|entry|1.0.0|src/main/ets/entryability/EntryAbility.ts;entry;false;ets
|
||||
/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/Index.ts;&entry/src/main/ets/pages/Index&;esm;entry|entry|1.0.0|src/main/ets/pages/Index.ts;entry;false;ets
|
||||
/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/MainPage.ts;&entry/src/main/ets/pages/MainPage&;esm;entry|entry|1.0.0|src/main/ets/pages/MainPage.ts;entry;false;ets
|
||||
/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/model/GraphDatabase.ts;&entry/src/main/ets/model/GraphDatabase&;esm;entry|entry|1.0.0|src/main/ets/model/GraphDatabase.ts;entry;false;ets
|
||||
/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/SettingsPage.ts;&entry/src/main/ets/pages/SettingsPage&;esm;entry|entry|1.0.0|src/main/ets/pages/SettingsPage.ts;entry;false;ets
|
||||
/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/GraphPage.ts;&entry/src/main/ets/pages/GraphPage&;esm;entry|entry|1.0.0|src/main/ets/pages/GraphPage.ts;entry;false;ets
|
||||
/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/ChatPage.ts;&entry/src/main/ets/pages/ChatPage&;esm;entry|entry|1.0.0|src/main/ets/pages/ChatPage.ts;entry;false;ets
|
||||
9
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/modules.cache
vendored
Normal file
9
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/modules.cache
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/build/default/generated/r/default/ResourceTable.js;/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/build/default/generated/r/default/ResourceTable.protoBin
|
||||
/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/entryability/EntryAbility.ts;/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/entryability/EntryAbility.protoBin
|
||||
/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/Index.ts;/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/Index.protoBin
|
||||
/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/MainPage.ts;/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/MainPage.protoBin
|
||||
/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/model/GraphDatabase.ts;/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/model/GraphDatabase.protoBin
|
||||
/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/SettingsPage.ts;/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/SettingsPage.protoBin
|
||||
/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/GraphPage.ts;/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/GraphPage.protoBin
|
||||
/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/ChatPage.ts;/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/ChatPage.protoBin
|
||||
/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/npmEntries.txt;/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/npmEntries.protoBin
|
||||
BIN
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/npmEntries.protoBin
vendored
Normal file
BIN
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/npmEntries.protoBin
vendored
Normal file
Binary file not shown.
7
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/npmEntries.txt
vendored
Normal file
7
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/npmEntries.txt
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
@system.app:@native.system.app
|
||||
@ohos.app:@native.ohos.app
|
||||
@system.router:@native.system.router
|
||||
@system.curves:@native.system.curves
|
||||
@ohos.curves:@native.ohos.curves
|
||||
@system.matrix4:@native.system.matrix4
|
||||
@ohos.matrix4:@native.ohos.matrix4
|
||||
89
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/sourceMaps.json
vendored
Normal file
89
harmony/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/sourceMaps.json
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Use these variables when you tailor your ArkTS code. They must be of the const type.
|
||||
*/
|
||||
export const BUNDLE_NAME = 'com.trulymem.app';
|
||||
export const BUNDLE_TYPE = 'app';
|
||||
export const VERSION_CODE = 1000001;
|
||||
export const VERSION_NAME = '1.0.0';
|
||||
export const TARGET_NAME = 'default';
|
||||
export const PRODUCT_NAME = 'default';
|
||||
export const BUILD_MODE_NAME = 'debug';
|
||||
export const DEBUG = true;
|
||||
|
||||
/**
|
||||
* BuildProfile Class is used only for compatibility purposes.
|
||||
*/
|
||||
export default class BuildProfile {
|
||||
static readonly BUNDLE_NAME = BUNDLE_NAME;
|
||||
static readonly BUNDLE_TYPE = BUNDLE_TYPE;
|
||||
static readonly VERSION_CODE = VERSION_CODE;
|
||||
static readonly VERSION_NAME = VERSION_NAME;
|
||||
static readonly TARGET_NAME = TARGET_NAME;
|
||||
static readonly PRODUCT_NAME = PRODUCT_NAME;
|
||||
static readonly BUILD_MODE_NAME = BUILD_MODE_NAME;
|
||||
static readonly DEBUG = DEBUG;
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef RESOURCE_TABLE_H
|
||||
#define RESOURCE_TABLE_H
|
||||
|
||||
#include<stdint.h>
|
||||
|
||||
namespace OHOS {
|
||||
const int32_t STRING_ENTRYABILITY_DESC = 0x01000001;
|
||||
const int32_t STRING_ENTRYABILITY_LABEL = 0x01000002;
|
||||
const int32_t STRING_APP_NAME = 0x01000003;
|
||||
const int32_t STRING_MODULE_DESC = 0x01000004;
|
||||
const int32_t COLOR_START_WINDOW_BACKGROUND = 0x01000005;
|
||||
const int32_t MEDIA_LAYERED_IMAGE = 0x01000000;
|
||||
const int32_t MEDIA_STARTICON = 0x01000006;
|
||||
const int32_t PROFILE_MAIN_PAGES = 0x01000007;
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//@ts-noCheck
|
||||
@ -0,0 +1 @@
|
||||
[{"hapName":"entry-default-unsigned.hap","deviceTypes":["phone","tablet","2in1"],"isSigned":false}]
|
||||
@ -0,0 +1,26 @@
|
||||
{
|
||||
"modulePathMap": {
|
||||
"entry": "/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry",
|
||||
"trulymem-core": "/home/program/TrulyMEM-TrueHumanMEM/harmonyos/trulymem-core"
|
||||
},
|
||||
"compileMode": "esmodule",
|
||||
"projectRootPath": "/home/program/TrulyMEM-TrueHumanMEM/harmonyos",
|
||||
"nodeModulesPath": "/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/intermediates/loader_out/default/node_modules",
|
||||
"byteCodeHarInfo": {},
|
||||
"declarationEntry": [],
|
||||
"moduleName": "entry",
|
||||
"hspNameOhmMap": {},
|
||||
"harNameOhmMap": {},
|
||||
"packageManagerType": "ohpm",
|
||||
"compileEntry": [
|
||||
"/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/generated/r/default/ResourceTable.ts"
|
||||
],
|
||||
"otherCompileFiles": [],
|
||||
"dynamicImportLibInfo": {},
|
||||
"routerMap": [],
|
||||
"hspResourcesMap": {},
|
||||
"updateVersionInfo": {},
|
||||
"customizedHar": false,
|
||||
"anBuildOutPut": "/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/intermediates/loader_out/default/an/arm64-v8a",
|
||||
"anBuildMode": "type"
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
{"entry":{"packageName":"entry","bundleName":"","moduleName":"","version":"","entryPath":"src/main/","isSO":false,"dependencyAlias":""}}
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -0,0 +1,66 @@
|
||||
{
|
||||
"app": {
|
||||
"bundleName": "com.trulymem.app",
|
||||
"vendor": "trulymem",
|
||||
"versionCode": 1000001,
|
||||
"versionName": "1.0.0",
|
||||
"icon": "$media:layered_image",
|
||||
"label": "$string:app_name",
|
||||
"apiReleaseType": "Release",
|
||||
"compileSdkVersion": "6.1.0.105",
|
||||
"targetAPIVersion": 60100023,
|
||||
"minAPIVersion": 60100023,
|
||||
"compileSdkType": "HarmonyOS",
|
||||
"targetMinorAPIVersion": 0,
|
||||
"targetPatchAPIVersion": 0,
|
||||
"appEnvironments": [],
|
||||
"bundleType": "app",
|
||||
"buildMode": "debug",
|
||||
"debug": true
|
||||
},
|
||||
"module": {
|
||||
"name": "entry",
|
||||
"type": "entry",
|
||||
"description": "$string:module_desc",
|
||||
"mainElement": "EntryAbility",
|
||||
"deviceTypes": [
|
||||
"phone",
|
||||
"tablet",
|
||||
"2in1"
|
||||
],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
"pages": "$profile:main_pages",
|
||||
"abilities": [
|
||||
{
|
||||
"name": "EntryAbility",
|
||||
"srcEntry": "./ets/entryability/EntryAbility.ets",
|
||||
"description": "$string:EntryAbility_desc",
|
||||
"icon": "$media:layered_image",
|
||||
"label": "$string:EntryAbility_label",
|
||||
"startWindowIcon": "$media:startIcon",
|
||||
"startWindowBackground": "$color:start_window_background",
|
||||
"exported": true,
|
||||
"skills": [
|
||||
{
|
||||
"entities": [
|
||||
"entity.system.home"
|
||||
],
|
||||
"actions": [
|
||||
"action.system.home"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"requestPermissions": [
|
||||
{
|
||||
"name": "ohos.permission.INTERNET"
|
||||
},
|
||||
{
|
||||
"name": "ohos.permission.GET_NETWORK_INFO"
|
||||
}
|
||||
],
|
||||
"packageName": "entry"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
{"app":{"bundleName":"com.trulymem.app","vendor":"trulymem","versionCode":1000001,"versionName":"1.0.0","icon":"$media:layered_image","label":"$string:app_name","apiReleaseType":"Release","compileSdkVersion":"6.1.0.105","targetAPIVersion":60100023,"minAPIVersion":60100023,"compileSdkType":"HarmonyOS","targetMinorAPIVersion":0,"targetPatchAPIVersion":0,"appEnvironments":[],"bundleType":"app","buildMode":"debug","debug":true,"iconId":16777216,"labelId":16777219},"module":{"name":"entry","type":"entry","description":"$string:module_desc","mainElement":"EntryAbility","deviceTypes":["phone","tablet","2in1"],"deliveryWithInstall":true,"installationFree":false,"pages":"$profile:main_pages","abilities":[{"name":"EntryAbility","srcEntry":"./ets/entryability/EntryAbility.ets","description":"$string:EntryAbility_desc","icon":"$media:layered_image","label":"$string:EntryAbility_label","startWindowIcon":"$media:startIcon","startWindowBackground":"$color:start_window_background","exported":true,"skills":[{"entities":["entity.system.home"],"actions":["action.system.home"]}],"descriptionId":16777217,"iconId":16777216,"labelId":16777218,"startWindowIconId":16777222,"startWindowBackgroundId":16777221}],"requestPermissions":[{"name":"ohos.permission.INTERNET"},{"name":"ohos.permission.GET_NETWORK_INFO"}],"packageName":"entry","virtualMachine":"ark13.0.1.0","compileMode":"esmodule","dependencies":[],"descriptionId":16777220}}
|
||||
@ -0,0 +1 @@
|
||||
{"libs":{},"stripped":{}}
|
||||
@ -0,0 +1 @@
|
||||
{"libs":{},"binxo":{},"binxoSymbol":{"enableAsanBinxo":false,"excludeSoFromBinxo":[]}}
|
||||
@ -0,0 +1,69 @@
|
||||
{
|
||||
"app": {
|
||||
"bundleName": "com.trulymem.app",
|
||||
"vendor": "trulymem",
|
||||
"versionCode": 1000001,
|
||||
"versionName": "1.0.0",
|
||||
"icon": "$media:layered_image",
|
||||
"label": "$string:app_name",
|
||||
"apiReleaseType": "Release",
|
||||
"compileSdkVersion": "6.1.0.105",
|
||||
"targetAPIVersion": 60100023,
|
||||
"minAPIVersion": 60100023,
|
||||
"compileSdkType": "HarmonyOS",
|
||||
"targetMinorAPIVersion": 0,
|
||||
"targetPatchAPIVersion": 0,
|
||||
"appEnvironments": [],
|
||||
"bundleType": "app",
|
||||
"buildMode": "debug",
|
||||
"debug": true
|
||||
},
|
||||
"module": {
|
||||
"name": "entry",
|
||||
"type": "entry",
|
||||
"description": "$string:module_desc",
|
||||
"mainElement": "EntryAbility",
|
||||
"deviceTypes": [
|
||||
"phone",
|
||||
"tablet",
|
||||
"2in1"
|
||||
],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
"pages": "$profile:main_pages",
|
||||
"abilities": [
|
||||
{
|
||||
"name": "EntryAbility",
|
||||
"srcEntry": "./ets/entryability/EntryAbility.ets",
|
||||
"description": "$string:EntryAbility_desc",
|
||||
"icon": "$media:layered_image",
|
||||
"label": "$string:EntryAbility_label",
|
||||
"startWindowIcon": "$media:startIcon",
|
||||
"startWindowBackground": "$color:start_window_background",
|
||||
"exported": true,
|
||||
"skills": [
|
||||
{
|
||||
"entities": [
|
||||
"entity.system.home"
|
||||
],
|
||||
"actions": [
|
||||
"action.system.home"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"requestPermissions": [
|
||||
{
|
||||
"name": "ohos.permission.INTERNET"
|
||||
},
|
||||
{
|
||||
"name": "ohos.permission.GET_NETWORK_INFO"
|
||||
}
|
||||
],
|
||||
"packageName": "entry",
|
||||
"virtualMachine": "ark13.0.1.0",
|
||||
"compileMode": "esmodule",
|
||||
"dependencies": []
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
string EntryAbility_desc 0x01000001
|
||||
string EntryAbility_label 0x01000002
|
||||
string app_name 0x01000003
|
||||
string module_desc 0x01000004
|
||||
color start_window_background 0x01000005
|
||||
media layered_image 0x01000000
|
||||
media startIcon 0x01000006
|
||||
profile main_pages 0x01000007
|
||||
@ -0,0 +1 @@
|
||||
{"app":{"bundleName":"com.trulymem.app","vendor":"trulymem","versionCode":1000001,"versionName":"1.0.0","icon":"$media:layered_image","label":"$string:app_name","apiReleaseType":"Release","compileSdkVersion":"6.1.0.105","targetAPIVersion":60100023,"minAPIVersion":60100023,"compileSdkType":"HarmonyOS","targetMinorAPIVersion":0,"targetPatchAPIVersion":0,"appEnvironments":[],"bundleType":"app","buildMode":"debug","debug":true},"module":{"name":"entry","type":"entry","description":"$string:module_desc","mainElement":"EntryAbility","deviceTypes":["phone","tablet","2in1"],"deliveryWithInstall":true,"installationFree":false,"pages":"$profile:main_pages","abilities":[{"name":"EntryAbility","srcEntry":"./ets/entryability/EntryAbility.ets","description":"$string:EntryAbility_desc","icon":"$media:layered_image","label":"$string:EntryAbility_label","startWindowIcon":"$media:startIcon","startWindowBackground":"$color:start_window_background","exported":true,"skills":[{"entities":["entity.system.home"],"actions":["action.system.home"]}]}],"requestPermissions":[{"name":"ohos.permission.INTERNET"},{"name":"ohos.permission.GET_NETWORK_INFO"}],"packageName":"entry","virtualMachine":"ark13.0.1.0","compileMode":"esmodule","dependencies":[]}}
|
||||
@ -0,0 +1,35 @@
|
||||
{
|
||||
"record": [{
|
||||
"type": "media",
|
||||
"name": "layered_image",
|
||||
"id": "0x01000000"
|
||||
}, {
|
||||
"type": "string",
|
||||
"name": "EntryAbility_desc",
|
||||
"id": "0x01000001"
|
||||
}, {
|
||||
"type": "string",
|
||||
"name": "EntryAbility_label",
|
||||
"id": "0x01000002"
|
||||
}, {
|
||||
"type": "string",
|
||||
"name": "app_name",
|
||||
"id": "0x01000003"
|
||||
}, {
|
||||
"type": "string",
|
||||
"name": "module_desc",
|
||||
"id": "0x01000004"
|
||||
}, {
|
||||
"type": "color",
|
||||
"name": "start_window_background",
|
||||
"id": "0x01000005"
|
||||
}, {
|
||||
"type": "media",
|
||||
"name": "startIcon",
|
||||
"id": "0x01000006"
|
||||
}, {
|
||||
"type": "profile",
|
||||
"name": "main_pages",
|
||||
"id": "0x01000007"
|
||||
}]
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
{
|
||||
"app": {
|
||||
"bundleName": "com.trulymem.app",
|
||||
"vendor": "trulymem",
|
||||
"versionCode": 1000001,
|
||||
"versionName": "1.0.0",
|
||||
"icon": "$media:layered_image",
|
||||
"label": "$string:app_name",
|
||||
"apiReleaseType": "Release",
|
||||
"compileSdkVersion": "6.1.0.105",
|
||||
"targetAPIVersion": 60100023,
|
||||
"minAPIVersion": 60100023,
|
||||
"compileSdkType": "HarmonyOS",
|
||||
"targetMinorAPIVersion": 0,
|
||||
"targetPatchAPIVersion": 0,
|
||||
"appEnvironments": [],
|
||||
"bundleType": "app",
|
||||
"buildMode": "debug",
|
||||
"debug": true,
|
||||
"iconId": 16777216,
|
||||
"labelId": 16777219
|
||||
},
|
||||
"module": {
|
||||
"name": "entry",
|
||||
"type": "entry",
|
||||
"description": "$string:module_desc",
|
||||
"mainElement": "EntryAbility",
|
||||
"deviceTypes": ["phone", "tablet", "2in1"],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
"pages": "$profile:main_pages",
|
||||
"abilities": [{
|
||||
"name": "EntryAbility",
|
||||
"srcEntry": "./ets/entryability/EntryAbility.ets",
|
||||
"description": "$string:EntryAbility_desc",
|
||||
"icon": "$media:layered_image",
|
||||
"label": "$string:EntryAbility_label",
|
||||
"startWindowIcon": "$media:startIcon",
|
||||
"startWindowBackground": "$color:start_window_background",
|
||||
"exported": true,
|
||||
"skills": [{
|
||||
"entities": ["entity.system.home"],
|
||||
"actions": ["action.system.home"]
|
||||
}],
|
||||
"descriptionId": 16777217,
|
||||
"iconId": 16777216,
|
||||
"labelId": 16777218,
|
||||
"startWindowIconId": 16777222,
|
||||
"startWindowBackgroundId": 16777221
|
||||
}],
|
||||
"requestPermissions": [{
|
||||
"name": "ohos.permission.INTERNET"
|
||||
}, {
|
||||
"name": "ohos.permission.GET_NETWORK_INFO"
|
||||
}],
|
||||
"packageName": "entry",
|
||||
"virtualMachine": "ark13.0.1.0",
|
||||
"compileMode": "esmodule",
|
||||
"dependencies": [],
|
||||
"descriptionId": 16777220
|
||||
}
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
{"context":{"extensionPath":"/home/program/tools/command-line-tools/sdk/default/hms/toolchains/lib/libimage_transcoder_shared.so"},"compression":{"media":{"enable":false},"filters":[]}}
|
||||
@ -0,0 +1 @@
|
||||
{"configPath":"/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/intermediates/process_profile/default/module.json","packageName":"com.trulymem.app","output":"/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/intermediates/res/default","moduleNames":"entry,trulymem-core","ResourceTable":["/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/generated/r/default/ResourceTable.h","/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/generated/r/default/ResourceTable.ts"],"applicationResource":"/home/program/TrulyMEM-TrueHumanMEM/harmonyos/AppScope/resources","moduleResources":["/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/src/main/resources"],"dependencies":[],"iconCheck":true,"compression":"/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/intermediates/res/default/opt-compression.json","ids":"/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/intermediates/res/default/ids_map","definedIds":"/home/program/TrulyMEM-TrueHumanMEM/harmonyos/entry/build/default/intermediates/res/default/ids_map/id_defined.json","definedSysIds":"/home/program/tools/command-line-tools/sdk/default/hms/toolchains/id_defined.json"}
|
||||
Binary file not shown.
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">
|
||||
<rect width="200" height="200" rx="30" fill="#6366f1"/>
|
||||
<text x="100" y="130" font-family="Arial" font-size="80" fill="white" text-anchor="middle" font-weight="bold">T</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 313 B |
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">
|
||||
<rect width="200" height="200" rx="20" fill="#6366f1"/>
|
||||
<text x="100" y="130" font-family="Arial" font-size="60" fill="white" text-anchor="middle" font-weight="bold">TM</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 314 B |
@ -0,0 +1,5 @@
|
||||
{
|
||||
"src": [
|
||||
"pages/Index"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,302 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>记忆星图 - TrulyMEM</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body { font-family: 'Courier New', monospace; background: #0a0a1a; color: #ffffff; overflow: hidden; width: 100vw; height: 100vh; }
|
||||
#canvas-container { width: 100%; height: 100%; position: relative; }
|
||||
canvas { display: block; }
|
||||
#stats { position: absolute; top: 20px; left: 20px; background: rgba(10, 10, 26, 0.8); padding: 15px 20px; border-radius: 8px; border: 1px solid rgba(100, 100, 255, 0.3); font-size: 14px; z-index: 100; backdrop-filter: blur(10px); }
|
||||
#stats h3 { margin-bottom: 8px; color: #4488ff; font-size: 16px; }
|
||||
#stats p { margin: 4px 0; color: #aaaacc; }
|
||||
#stats span { color: #ffffff; font-weight: bold; }
|
||||
#node-info { position: absolute; top: 20px; right: 20px; background: rgba(10, 10, 26, 0.9); padding: 15px 20px; border-radius: 8px; border: 1px solid rgba(100, 100, 255, 0.3); font-size: 14px; z-index: 100; display: none; backdrop-filter: blur(10px); max-width: 300px; }
|
||||
#node-info h3 { color: #44ff88; margin-bottom: 8px; font-size: 16px; }
|
||||
#node-info p { margin: 4px 0; color: #aaaacc; }
|
||||
#node-info .label { color: #8888aa; }
|
||||
#loading { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 20px; color: #4488ff; z-index: 200; }
|
||||
#nav { position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%); display: flex; gap: 20px; z-index: 100; }
|
||||
.nav-btn { background: rgba(10, 10, 26, 0.8); border: 1px solid rgba(100, 100, 255, 0.3); color: #aaaacc; padding: 12px 24px; border-radius: 8px; cursor: pointer; font-family: 'Courier New', monospace; font-size: 14px; backdrop-filter: blur(10px); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="canvas-container">
|
||||
<div id="loading">正在加载星图数据...</div>
|
||||
<div id="stats">
|
||||
<h3>🌌 记忆星图</h3>
|
||||
<p>节点: <span id="node-count">0</span></p>
|
||||
<p>边: <span id="edge-count">0</span></p>
|
||||
<p>状态: <span id="status">初始化中...</span></p>
|
||||
</div>
|
||||
<div id="node-info">
|
||||
<h3 id="info-name"></h3>
|
||||
<p><span class="label">类型:</span> <span id="info-type"></span></p>
|
||||
<p><span class="label">提及次数:</span> <span id="info-mentions"></span></p>
|
||||
<p><span class="label">连接数:</span> <span id="info-links"></span></p>
|
||||
</div>
|
||||
<div id="nav">
|
||||
<button class="nav-btn active">🌌 星图</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
||||
<script>
|
||||
let scene, camera, renderer, controls;
|
||||
let nodes = [], edges = [];
|
||||
let nodeMeshes = [], edgeLines = [];
|
||||
let starField, nebulaParticles;
|
||||
let raycaster, mouse;
|
||||
let hoveredNode = null, selectedNode = null;
|
||||
let animationId;
|
||||
let highlightPulse = 0;
|
||||
|
||||
const typeColors = { 'person': 0x4488ff, 'task': 0xff8844, 'ai': 0xaa44ff, 'concept': 0x44ff88, 'object': 0xff4444 };
|
||||
const defaultColor = 0xcccccc;
|
||||
const edgeColors = { '喜欢': 0xff6b6b, '学习': 0x4ecdc4, '属于': 0x45b7d1, '相关': 0x96ceb4, '使用': 0xfeca57, '创建': 0xff9ff3 };
|
||||
const defaultEdgeColor = 0x444466;
|
||||
|
||||
function init() {
|
||||
scene = new THREE.Scene();
|
||||
scene.fog = new THREE.FogExp2(0x0a0a1a, 0.015);
|
||||
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 2000);
|
||||
camera.position.set(0, 30, 60);
|
||||
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
renderer.setClearColor(0x0a0a1a, 1);
|
||||
document.getElementById('canvas-container').appendChild(renderer.domElement);
|
||||
controls = new THREE.OrbitControls(camera, renderer.domElement);
|
||||
controls.enableDamping = true;
|
||||
controls.dampingFactor = 0.05;
|
||||
const ambientLight = new THREE.AmbientLight(0x444466, 0.6);
|
||||
scene.add(ambientLight);
|
||||
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
|
||||
directionalLight.position.set(50, 100, 50);
|
||||
scene.add(directionalLight);
|
||||
raycaster = new THREE.Raycaster();
|
||||
mouse = new THREE.Vector2();
|
||||
createStarField();
|
||||
createNebula();
|
||||
window.addEventListener('resize', onWindowResize);
|
||||
renderer.domElement.addEventListener('mousemove', onMouseMove);
|
||||
renderer.domElement.addEventListener('click', onMouseClick);
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.data.type === 'graph_data') {
|
||||
window.__graphData = event.data.payload;
|
||||
loadGraphData();
|
||||
}
|
||||
});
|
||||
window.parent.postMessage('request_graph_data', '*');
|
||||
animate();
|
||||
}
|
||||
|
||||
function createStarField() {
|
||||
const starCount = 3000;
|
||||
const positions = new Float32Array(starCount * 3);
|
||||
const colors = new Float32Array(starCount * 3);
|
||||
for (let i = 0; i < starCount; i++) {
|
||||
const i3 = i * 3;
|
||||
const radius = 400 + Math.random() * 600;
|
||||
const theta = Math.random() * Math.PI * 2;
|
||||
const phi = Math.acos(2 * Math.random() - 1);
|
||||
positions[i3] = radius * Math.sin(phi) * Math.cos(theta);
|
||||
positions[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
|
||||
positions[i3 + 2] = radius * Math.cos(phi);
|
||||
const colorChoice = Math.random();
|
||||
if (colorChoice < 0.7) {
|
||||
colors[i3] = 0.8 + Math.random() * 0.2;
|
||||
colors[i3 + 1] = 0.8 + Math.random() * 0.2;
|
||||
colors[i3 + 2] = 1.0;
|
||||
} else {
|
||||
colors[i3] = 1.0;
|
||||
colors[i3 + 1] = 0.9 + Math.random() * 0.1;
|
||||
colors[i3 + 2] = 0.8 + Math.random() * 0.2;
|
||||
}
|
||||
}
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
||||
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
|
||||
const material = new THREE.PointsMaterial({ size: 1.5, vertexColors: true, transparent: true, opacity: 0.8, sizeAttenuation: true });
|
||||
starField = new THREE.Points(geometry, material);
|
||||
scene.add(starField);
|
||||
}
|
||||
|
||||
function createNebula() {
|
||||
const nebulaCount = 500;
|
||||
const positions = new Float32Array(nebulaCount * 3);
|
||||
const colors = new Float32Array(nebulaCount * 3);
|
||||
for (let i = 0; i < nebulaCount; i++) {
|
||||
const i3 = i * 3;
|
||||
positions[i3] = (Math.random() - 0.5) * 800;
|
||||
positions[i3 + 1] = (Math.random() - 0.5) * 800;
|
||||
positions[i3 + 2] = (Math.random() - 0.5) * 800;
|
||||
const colorChoice = Math.random();
|
||||
if (colorChoice < 0.33) {
|
||||
colors[i3] = 0.5 + Math.random() * 0.3; colors[i3 + 1] = 0.2 + Math.random() * 0.2; colors[i3 + 2] = 0.7 + Math.random() * 0.3;
|
||||
} else if (colorChoice < 0.66) {
|
||||
colors[i3] = 0.2 + Math.random() * 0.2; colors[i3 + 1] = 0.3 + Math.random() * 0.3; colors[i3 + 2] = 0.8 + Math.random() * 0.2;
|
||||
} else {
|
||||
colors[i3] = 0.7 + Math.random() * 0.3; colors[i3 + 1] = 0.2 + Math.random() * 0.2; colors[i3 + 2] = 0.5 + Math.random() * 0.3;
|
||||
}
|
||||
}
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
||||
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
|
||||
const material = new THREE.PointsMaterial({ size: 8, vertexColors: true, transparent: true, opacity: 0.15, sizeAttenuation: true, blending: THREE.AdditiveBlending });
|
||||
nebulaParticles = new THREE.Points(geometry, material);
|
||||
scene.add(nebulaParticles);
|
||||
}
|
||||
|
||||
window.loadGraphData = function(data) {
|
||||
if (data && data.nodes && data.edges) {
|
||||
nodes = data.nodes.map(n => ({ id: n.id, name: n.label || n.name, type: n.type, mention_count: n.mentions || 1 }));
|
||||
edges = data.edges.map(e => ({ id: e.id, source: e.from || e.source, target: e.to || e.target, relation_type: e.label || e.relation }));
|
||||
document.getElementById('node-count').textContent = nodes.length;
|
||||
document.getElementById('edge-count').textContent = edges.length;
|
||||
document.getElementById('status').textContent = '就绪';
|
||||
createGraphVisualization();
|
||||
document.getElementById('loading').style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function createGraphVisualization() {
|
||||
nodeMeshes.forEach(mesh => scene.remove(mesh));
|
||||
edgeLines.forEach(line => scene.remove(line));
|
||||
nodeMeshes = [];
|
||||
edgeLines = [];
|
||||
if (nodes.length === 0) return;
|
||||
const nodeDegrees = {};
|
||||
nodes.forEach(n => nodeDegrees[n.id] = 0);
|
||||
edges.forEach(e => {
|
||||
nodeDegrees[e.source] = (nodeDegrees[e.source] || 0) + 1;
|
||||
nodeDegrees[e.target] = (nodeDegrees[e.target] || 0) + 1;
|
||||
});
|
||||
const positions = {};
|
||||
const maxDegree = Math.max(...Object.values(nodeDegrees), 1);
|
||||
nodes.forEach((node, i) => {
|
||||
const angle = (i / nodes.length) * Math.PI * 2;
|
||||
const radius = 15 + (nodeDegrees[node.id] / maxDegree) * 35;
|
||||
positions[node.id] = { x: radius * Math.cos(angle), y: (Math.random() - 0.5) * 10, z: radius * Math.sin(angle) };
|
||||
});
|
||||
for (let iter = 0; iter < 50; iter++) {
|
||||
Object.keys(positions).forEach(id1 => {
|
||||
Object.keys(positions).forEach(id2 => {
|
||||
if (id1 >= id2) return;
|
||||
const pos1 = positions[id1], pos2 = positions[id2];
|
||||
const dx = pos1.x - pos2.x, dy = pos1.y - pos2.y, dz = pos1.z - pos2.z;
|
||||
const dist = Math.sqrt(dx*dx + dy*dy + dz*dz) + 0.1;
|
||||
if (dist < 10) {
|
||||
const force = 0.1 / dist;
|
||||
pos1.x += (dx/dist)*force; pos1.y += (dy/dist)*force; pos1.z += (dz/dist)*force;
|
||||
pos2.x -= (dx/dist)*force; pos2.y -= (dy/dist)*force; pos2.z -= (dz/dist)*force;
|
||||
}
|
||||
});
|
||||
});
|
||||
edges.forEach(edge => {
|
||||
const pos1 = positions[edge.source], pos2 = positions[edge.target];
|
||||
if (!pos1 || !pos2) return;
|
||||
const dx = pos2.x - pos1.x, dy = pos2.y - pos1.y, dz = pos2.z - pos1.z;
|
||||
const dist = Math.sqrt(dx*dx + dy*dy + dz*dz) + 0.1;
|
||||
if (dist > 15) {
|
||||
const force = 0.05;
|
||||
pos1.x += (dx/dist)*force; pos1.y += (dy/dist)*force; pos1.z += (dz/dist)*force;
|
||||
pos2.x -= (dx/dist)*force; pos2.y -= (dy/dist)*force; pos2.z -= (dz/dist)*force;
|
||||
}
|
||||
});
|
||||
}
|
||||
nodes.forEach(node => {
|
||||
const pos = positions[node.id];
|
||||
if (!pos) return;
|
||||
const radius = 0.4 + Math.min(node.mention_count * 0.15, 1.5);
|
||||
const color = typeColors[node.type] || defaultColor;
|
||||
const geometry = new THREE.SphereGeometry(radius, 16, 12);
|
||||
const material = new THREE.MeshPhongMaterial({ color: color, emissive: color, emissiveIntensity: 0.5 + Math.min(node.mention_count * 0.05, 0.3), shininess: 30 });
|
||||
const sphere = new THREE.Mesh(geometry, material);
|
||||
sphere.position.set(pos.x, pos.y, pos.z);
|
||||
sphere.userData = { nodeId: node.id, nodeData: node };
|
||||
scene.add(sphere);
|
||||
nodeMeshes.push(sphere);
|
||||
});
|
||||
edges.forEach(edge => {
|
||||
const pos1 = positions[edge.source], pos2 = positions[edge.target];
|
||||
if (!pos1 || !pos2) return;
|
||||
const color = edgeColors[edge.relation_type] || defaultEdgeColor;
|
||||
const geometry = new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(pos1.x, pos1.y, pos1.z), new THREE.Vector3(pos2.x, pos2.y, pos2.z)]);
|
||||
const material = new THREE.LineBasicMaterial({ color: color, transparent: true, opacity: 0.4, linewidth: 1 });
|
||||
const line = new THREE.Line(geometry, material);
|
||||
line.userData = { edgeId: edge.id, edgeData: edge };
|
||||
scene.add(line);
|
||||
edgeLines.push(line);
|
||||
});
|
||||
const allPositions = Object.values(positions);
|
||||
if (allPositions.length > 0) {
|
||||
let maxDist = 0;
|
||||
allPositions.forEach(pos => { maxDist = Math.max(maxDist, Math.sqrt(pos.x*pos.x + pos.y*pos.y + pos.z*pos.z)); });
|
||||
camera.position.set(maxDist * 2.2, maxDist * 1.5, maxDist * 2.2);
|
||||
controls.target.set(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseMove(event) {
|
||||
const rect = renderer.domElement.getBoundingClientRect();
|
||||
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
|
||||
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
|
||||
raycaster.setFromCamera(mouse, camera);
|
||||
const intersects = raycaster.intersectObjects(nodeMeshes);
|
||||
if (intersects.length > 0) {
|
||||
const node = intersects[0].object;
|
||||
if (hoveredNode !== node) {
|
||||
if (hoveredNode) hoveredNode.scale.set(1, 1, 1);
|
||||
hoveredNode = node;
|
||||
node.scale.set(1.2, 1.2, 1.2);
|
||||
showNodeInfo(node.userData.nodeData);
|
||||
}
|
||||
} else {
|
||||
if (hoveredNode) { hoveredNode.scale.set(1, 1, 1); hoveredNode = null; hideNodeInfo(); }
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseClick(event) {
|
||||
raycaster.setFromCamera(mouse, camera);
|
||||
const intersects = raycaster.intersectObjects(nodeMeshes);
|
||||
if (intersects.length > 0) {
|
||||
const node = intersects[0].object;
|
||||
if (selectedNode === node) { selectedNode = null; document.getElementById('node-info').style.display = 'none'; }
|
||||
else { selectedNode = node; showNodeInfo(node.userData.nodeData, true); }
|
||||
}
|
||||
}
|
||||
|
||||
function showNodeInfo(nodeData, isClick = false) {
|
||||
document.getElementById('info-name').textContent = nodeData.name;
|
||||
document.getElementById('info-type').textContent = nodeData.type;
|
||||
document.getElementById('info-mentions').textContent = nodeData.mention_count;
|
||||
const linkCount = edges.filter(e => e.source === nodeData.id || e.target === nodeData.id).length;
|
||||
document.getElementById('info-links').textContent = linkCount;
|
||||
if (isClick) document.getElementById('node-info').style.display = 'block';
|
||||
}
|
||||
|
||||
function hideNodeInfo() { if (!selectedNode) document.getElementById('node-info').style.display = 'none'; }
|
||||
|
||||
function onWindowResize() {
|
||||
camera.aspect = window.innerWidth / window.innerHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
}
|
||||
|
||||
function animate() {
|
||||
animationId = requestAnimationFrame(animate);
|
||||
const time = Date.now() * 0.001;
|
||||
highlightPulse = (highlightPulse + 0.02) % (Math.PI * 2);
|
||||
controls.update();
|
||||
if (starField) starField.rotation.y += 0.0001;
|
||||
if (hoveredNode) { const pulse = 1 + Math.sin(highlightPulse * 3) * 0.05; hoveredNode.scale.set(pulse * 1.2, pulse * 1.2, pulse * 1.2); }
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
init();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1 @@
|
||||
{"routerMap":[]}
|
||||
@ -0,0 +1 @@
|
||||
{"routerMap":[]}
|
||||
@ -0,0 +1 @@
|
||||
{"crossAppSharedConfig":[]}
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
1
harmony/entry/build/default/outputs/default/pack.info
Normal file
1
harmony/entry/build/default/outputs/default/pack.info
Normal file
@ -0,0 +1 @@
|
||||
{"summary":{"app":{"bundleName":"com.trulymem.app","bundleType":"app","version":{"code":1000001,"name":"1.0.0"}},"modules":[{"mainAbility":"EntryAbility","deviceType":["phone","tablet","2in1"],"abilities":[{"name":"EntryAbility","label":"$string:EntryAbility_label"}],"distro":{"moduleType":"entry","installationFree":false,"deliveryWithInstall":true,"moduleName":"entry"},"apiVersion":{"compatible":23,"releaseType":"Release","target":23}}]},"packages":[{"deviceType":["phone","tablet","2in1"],"moduleType":"entry","deliveryWithInstall":true,"name":"entry-default"}]}
|
||||
6
harmony/entry/hvigorfile.ts
Normal file
6
harmony/entry/hvigorfile.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { hapTasks } from '@ohos/hvigor-ohos-plugin';
|
||||
|
||||
export default {
|
||||
system: hapTasks,
|
||||
plugins: []
|
||||
};
|
||||
34
harmony/entry/obfuscation-rules.txt
Normal file
34
harmony/entry/obfuscation-rules.txt
Normal file
@ -0,0 +1,34 @@
|
||||
# Define project specific obfuscation rules here.
|
||||
# You can include the obfuscation configuration files in the current module's build-profile.json5.
|
||||
#
|
||||
# For more details, see
|
||||
# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5
|
||||
|
||||
# Obfuscation options:
|
||||
# -disable-obfuscation: disable all obfuscations
|
||||
# -enable-property-obfuscation: obfuscate the property names
|
||||
# -enable-toplevel-obfuscation: obfuscate the names in the global scope
|
||||
# -compact: remove unnecessary blank spaces and all line feeds
|
||||
# -remove-log: remove all console.* statements
|
||||
# -print-namecache: print the name cache that contains the mapping from the old names to new names
|
||||
# -apply-namecache: reuse the given cache file
|
||||
|
||||
# Keep options:
|
||||
# -keep-property-name: specifies property names that you want to keep
|
||||
# -keep-global-name: specifies names that you want to keep in the global scope
|
||||
|
||||
-enable-property-obfuscation
|
||||
-enable-toplevel-obfuscation
|
||||
-enable-filename-obfuscation
|
||||
-enable-export-obfuscation
|
||||
|
||||
# 保留JSON解析相关的属性名,防止混淆导致JSON解析失败
|
||||
-keep-property-name
|
||||
id
|
||||
name
|
||||
nameEn
|
||||
icon
|
||||
isCustom
|
||||
builtin
|
||||
custom
|
||||
pixelMap
|
||||
19
harmony/entry/oh-package-lock.json5
Normal file
19
harmony/entry/oh-package-lock.json5
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"meta": {
|
||||
"stableOrder": true,
|
||||
"enableUnifiedLockfile": false
|
||||
},
|
||||
"lockfileVersion": 3,
|
||||
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
|
||||
"specifiers": {
|
||||
"librcon@../librcon": "librcon@../librcon"
|
||||
},
|
||||
"packages": {
|
||||
"librcon@../librcon": {
|
||||
"name": "librcon",
|
||||
"version": "1.0.0",
|
||||
"resolved": "../librcon",
|
||||
"registryType": "local"
|
||||
}
|
||||
}
|
||||
}
|
||||
11
harmony/entry/oh-package.json5
Normal file
11
harmony/entry/oh-package.json5
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "entry",
|
||||
"version": "1.0.0",
|
||||
"description": "TrulyMEM - A personal memory and knowledge graph application.",
|
||||
"main": "",
|
||||
"author": "",
|
||||
"license": "",
|
||||
"dependencies": {
|
||||
"trulymem-core": "file:../trulymem-core"
|
||||
}
|
||||
}
|
||||
44
harmony/entry/src/main/ets/common/Constants.ets
Normal file
44
harmony/entry/src/main/ets/common/Constants.ets
Normal file
@ -0,0 +1,44 @@
|
||||
export class Constants {
|
||||
static readonly DB_NAME: string = 'trulymem.db';
|
||||
static readonly CONFIG_PREF_NAME: string = 'trulymem_config';
|
||||
static readonly DEFAULT_BASE_URL: string = 'https://api.deepseek.com';
|
||||
static readonly DEFAULT_MODEL: string = 'deepseek-chat';
|
||||
static readonly SECURITY_LEVEL: number = 1; // S1
|
||||
|
||||
// Table names
|
||||
static readonly TABLE_NODES: string = 'nodes';
|
||||
static readonly TABLE_RELATIONS: string = 'relations';
|
||||
static readonly TABLE_CHAT: string = 'chat_records';
|
||||
|
||||
// SQL definitions
|
||||
static readonly SQL_CREATE_NODES: string = `
|
||||
CREATE TABLE IF NOT EXISTS nodes (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
type TEXT DEFAULT 'concept',
|
||||
mentions INTEGER DEFAULT 1,
|
||||
created_at TEXT DEFAULT (datetime('now','localtime')),
|
||||
updated_at TEXT DEFAULT (datetime('now','localtime'))
|
||||
)`;
|
||||
|
||||
static readonly SQL_CREATE_RELATIONS: string = `
|
||||
CREATE TABLE IF NOT EXISTS relations (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
subject_id INTEGER NOT NULL,
|
||||
relation TEXT NOT NULL,
|
||||
object_id INTEGER NOT NULL,
|
||||
weight REAL DEFAULT 1.0,
|
||||
created_at TEXT DEFAULT (datetime('now','localtime')),
|
||||
FOREIGN KEY (subject_id) REFERENCES nodes(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (object_id) REFERENCES nodes(id) ON DELETE CASCADE
|
||||
)`;
|
||||
|
||||
static readonly SQL_CREATE_CHAT: string = `
|
||||
CREATE TABLE IF NOT EXISTS chat_records (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
role TEXT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
tools TEXT,
|
||||
created_at TEXT DEFAULT (datetime('now','localtime'))
|
||||
)`;
|
||||
}
|
||||
36
harmony/entry/src/main/ets/entryability/EntryAbility.ets
Normal file
36
harmony/entry/src/main/ets/entryability/EntryAbility.ets
Normal file
@ -0,0 +1,36 @@
|
||||
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
|
||||
import UIAbility from '@ohos.app.ability.UIAbility';
|
||||
import Window from '@ohos.window';
|
||||
import Want from '@ohos.app.ability.Want';
|
||||
|
||||
export default class EntryAbility extends UIAbility {
|
||||
onCreate(want: Want, param: AbilityConstant.LaunchParam): void {
|
||||
console.info('EntryAbility onCreate');
|
||||
}
|
||||
|
||||
onDestroy(): void {
|
||||
console.info('EntryAbility onDestroy');
|
||||
}
|
||||
|
||||
onWindowStageCreate(windowStage: Window.WindowStage): void {
|
||||
windowStage.loadContent('pages/Index', (err, data) => {
|
||||
if (err.code) {
|
||||
console.error('Failed to load content: ' + JSON.stringify(err));
|
||||
return;
|
||||
}
|
||||
console.info('Succeeded in loading content: ' + JSON.stringify(data));
|
||||
});
|
||||
}
|
||||
|
||||
onWindowStageDestroy(): void {
|
||||
console.info('EntryAbility onWindowStageDestroy');
|
||||
}
|
||||
|
||||
onForeground(): void {
|
||||
console.info('EntryAbility onForeground');
|
||||
}
|
||||
|
||||
onBackground(): void {
|
||||
console.info('EntryAbility onBackground');
|
||||
}
|
||||
}
|
||||
237
harmony/entry/src/main/ets/model/GraphDatabase.ets
Normal file
237
harmony/entry/src/main/ets/model/GraphDatabase.ets
Normal file
@ -0,0 +1,237 @@
|
||||
import relationalStore from '@ohos.data.relationalStore';
|
||||
import { Context } from '@ohos.abilityAccessCtrl';
|
||||
|
||||
interface TripletData {
|
||||
subject: string;
|
||||
relation: string;
|
||||
object: string;
|
||||
}
|
||||
|
||||
interface CriteriaData {
|
||||
subject?: string;
|
||||
target?: string;
|
||||
relation?: string;
|
||||
sessionId?: string;
|
||||
}
|
||||
|
||||
interface NodeData {
|
||||
id: number;
|
||||
label: string;
|
||||
type: string;
|
||||
mentions: number;
|
||||
}
|
||||
|
||||
interface EdgeData {
|
||||
from: number;
|
||||
to: number;
|
||||
label: string;
|
||||
weight: number;
|
||||
}
|
||||
|
||||
interface GraphData {
|
||||
nodes: NodeData[];
|
||||
edges: EdgeData[];
|
||||
}
|
||||
|
||||
interface RecallResult {
|
||||
data: GraphData;
|
||||
}
|
||||
|
||||
interface ChatMessage {
|
||||
role: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
interface CleanupResult {
|
||||
cleaned: number;
|
||||
}
|
||||
|
||||
const STORE_CONFIG: relationalStore.StoreConfig = {
|
||||
name: 'trulymem.db',
|
||||
securityLevel: relationalStore.SecurityLevel.S1
|
||||
};
|
||||
|
||||
export class GraphDatabase {
|
||||
private store?: relationalStore.RdbStore;
|
||||
private context?: Context;
|
||||
|
||||
async init(context: Context): Promise<void> {
|
||||
this.context = context;
|
||||
this.store = await relationalStore.getRdbStore(context, STORE_CONFIG);
|
||||
await this.createTables();
|
||||
}
|
||||
|
||||
private async createTables(): Promise<void> {
|
||||
if (!this.store) return;
|
||||
await this.store.executeSql(`
|
||||
CREATE TABLE IF NOT EXISTS nodes (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
type TEXT DEFAULT 'concept',
|
||||
mentions INTEGER DEFAULT 1,
|
||||
created_at TEXT,
|
||||
updated_at TEXT
|
||||
)
|
||||
`);
|
||||
await this.store.executeSql(`
|
||||
CREATE TABLE IF NOT EXISTS relations (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
subject_id INTEGER NOT NULL,
|
||||
relation TEXT NOT NULL,
|
||||
object_id INTEGER NOT NULL,
|
||||
weight REAL DEFAULT 1.0,
|
||||
created_at TEXT
|
||||
)
|
||||
`);
|
||||
await this.store.executeSql(`
|
||||
CREATE TABLE IF NOT EXISTS chat_records (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
role TEXT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
tools TEXT,
|
||||
created_at TEXT
|
||||
)
|
||||
`);
|
||||
}
|
||||
|
||||
async commit(triplets: TripletData[]): Promise<void> {
|
||||
if (!this.store) return;
|
||||
for (const triplet of triplets) {
|
||||
const subjectId: number = await this.upsertNode(triplet.subject);
|
||||
const objectId: number = await this.upsertNode(triplet.object);
|
||||
const bucket: relationalStore.ValuesBucket = {
|
||||
'subject_id': subjectId,
|
||||
'relation': triplet.relation,
|
||||
'object_id': objectId,
|
||||
'created_at': new Date().toISOString()
|
||||
};
|
||||
await this.store.insert('relations', bucket);
|
||||
}
|
||||
}
|
||||
|
||||
private async upsertNode(name: string): Promise<number> {
|
||||
if (!this.store) return -1;
|
||||
const predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('nodes');
|
||||
predicates.equalTo('name', name);
|
||||
const resultSet: relationalStore.ResultSet = await this.store.query(predicates, ['id']);
|
||||
if (resultSet.goToNextRow()) {
|
||||
const id: number = resultSet.getLong(resultSet.getColumnIndex('id'));
|
||||
resultSet.close();
|
||||
return id;
|
||||
}
|
||||
resultSet.close();
|
||||
const bucket: relationalStore.ValuesBucket = {
|
||||
'name': name,
|
||||
'type': 'concept',
|
||||
'created_at': new Date().toISOString(),
|
||||
'updated_at': new Date().toISOString()
|
||||
};
|
||||
return await this.store.insert('nodes', bucket);
|
||||
}
|
||||
|
||||
async recall(queryIntent: string, seedEntities?: string[]): Promise<RecallResult> {
|
||||
if (!this.store) {
|
||||
const empty: RecallResult = { data: { nodes: [], edges: [] } };
|
||||
return empty;
|
||||
}
|
||||
const nodes: NodeData[] = await this.getAllNodes();
|
||||
const edges: EdgeData[] = await this.getAllEdges();
|
||||
const result: RecallResult = { data: { nodes, edges } };
|
||||
return result;
|
||||
}
|
||||
|
||||
async purge(criteria: CriteriaData): Promise<void> {
|
||||
if (!this.store) return;
|
||||
const predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('nodes');
|
||||
await this.store.delete(predicates);
|
||||
}
|
||||
|
||||
async introspect(): Promise<RecallResult> {
|
||||
const nodes: NodeData[] = await this.getAllNodes();
|
||||
const edges: EdgeData[] = await this.getAllEdges();
|
||||
const result: RecallResult = { data: { nodes, edges } };
|
||||
return result;
|
||||
}
|
||||
|
||||
async archive(days: number): Promise<void> {
|
||||
// Archive old data - placeholder
|
||||
}
|
||||
|
||||
async cleanup(dryRun: boolean): Promise<CleanupResult> {
|
||||
const result: CleanupResult = { cleaned: 0 };
|
||||
return result;
|
||||
}
|
||||
|
||||
async saveChatMessage(role: string, content: string, tools?: string): Promise<void> {
|
||||
if (!this.store) return;
|
||||
const bucket: relationalStore.ValuesBucket = {
|
||||
'role': role,
|
||||
'content': content,
|
||||
'tools': tools || null,
|
||||
'created_at': new Date().toISOString()
|
||||
};
|
||||
await this.store.insert('chat_records', bucket);
|
||||
}
|
||||
|
||||
async getChatHistory(limit?: number): Promise<ChatMessage[]> {
|
||||
if (!this.store) return [];
|
||||
const predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('chat_records');
|
||||
predicates.orderByDesc('created_at');
|
||||
if (limit) {
|
||||
predicates.limitAs(limit);
|
||||
}
|
||||
const resultSet: relationalStore.ResultSet = await this.store.query(predicates, ['role', 'content']);
|
||||
const messages: ChatMessage[] = [];
|
||||
while (resultSet.goToNextRow()) {
|
||||
const msg: ChatMessage = {
|
||||
role: resultSet.getString(resultSet.getColumnIndex('role')),
|
||||
content: resultSet.getString(resultSet.getColumnIndex('content'))
|
||||
};
|
||||
messages.push(msg);
|
||||
}
|
||||
resultSet.close();
|
||||
return messages.reverse();
|
||||
}
|
||||
|
||||
async clearChatHistory(): Promise<void> {
|
||||
if (!this.store) return;
|
||||
const predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('chat_records');
|
||||
await this.store.delete(predicates);
|
||||
}
|
||||
|
||||
private async getAllNodes(): Promise<NodeData[]> {
|
||||
if (!this.store) return [];
|
||||
const predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('nodes');
|
||||
const resultSet: relationalStore.ResultSet = await this.store.query(predicates, ['id', 'name', 'type', 'mentions']);
|
||||
const nodes: NodeData[] = [];
|
||||
while (resultSet.goToNextRow()) {
|
||||
const node: NodeData = {
|
||||
id: resultSet.getLong(resultSet.getColumnIndex('id')),
|
||||
label: resultSet.getString(resultSet.getColumnIndex('name')),
|
||||
type: resultSet.getString(resultSet.getColumnIndex('type')),
|
||||
mentions: resultSet.getLong(resultSet.getColumnIndex('mentions'))
|
||||
};
|
||||
nodes.push(node);
|
||||
}
|
||||
resultSet.close();
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private async getAllEdges(): Promise<EdgeData[]> {
|
||||
if (!this.store) return [];
|
||||
const predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('relations');
|
||||
const resultSet: relationalStore.ResultSet = await this.store.query(predicates, ['subject_id', 'relation', 'object_id', 'weight']);
|
||||
const edges: EdgeData[] = [];
|
||||
while (resultSet.goToNextRow()) {
|
||||
const edge: EdgeData = {
|
||||
from: resultSet.getLong(resultSet.getColumnIndex('subject_id')),
|
||||
to: resultSet.getLong(resultSet.getColumnIndex('object_id')),
|
||||
label: resultSet.getString(resultSet.getColumnIndex('relation')),
|
||||
weight: resultSet.getDouble(resultSet.getColumnIndex('weight'))
|
||||
};
|
||||
edges.push(edge);
|
||||
}
|
||||
resultSet.close();
|
||||
return edges;
|
||||
}
|
||||
}
|
||||
100
harmony/entry/src/main/ets/pages/ChatPage.ets
Normal file
100
harmony/entry/src/main/ets/pages/ChatPage.ets
Normal file
@ -0,0 +1,100 @@
|
||||
import http from '@ohos.net.http';
|
||||
import dataPreferences from '@ohos.data.preferences';
|
||||
import { GraphDatabase } from '../model/GraphDatabase';
|
||||
|
||||
interface ChatMessage {
|
||||
role: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
@Component
|
||||
export struct ChatPage {
|
||||
@State messages: ChatMessage[] = [];
|
||||
@State inputText: string = '';
|
||||
@Prop db: GraphDatabase;
|
||||
private scrollController: Scroller = new Scroller();
|
||||
|
||||
async aboutToAppear() {
|
||||
this.messages = await this.db.getChatHistory(50);
|
||||
}
|
||||
|
||||
async sendMessage() {
|
||||
if (!this.inputText.trim()) return;
|
||||
|
||||
const userMessage: string = this.inputText;
|
||||
this.inputText = '';
|
||||
|
||||
await this.db.saveChatMessage('user', userMessage);
|
||||
const userMsg: ChatMessage = { role: 'user', content: userMessage };
|
||||
this.messages = [...this.messages, userMsg];
|
||||
|
||||
const pref: dataPreferences.Preferences =
|
||||
await dataPreferences.getPreferences(getContext(this), 'trulymem_config');
|
||||
const baseUrl: string = String(await pref.get('base_url', 'https://api.deepseek.com'));
|
||||
const model: string = String(await pref.get('model', 'deepseek-chat'));
|
||||
const apiKey: string = String(await pref.get('api_key', ''));
|
||||
|
||||
try {
|
||||
const httpRequest: http.HttpRequest = http.createHttp();
|
||||
const response: http.HttpResponse = await httpRequest.request(baseUrl + '/chat/completions', {
|
||||
method: http.RequestMethod.POST,
|
||||
header: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + apiKey
|
||||
},
|
||||
extraData: {
|
||||
model: model,
|
||||
messages: [{ role: 'user', content: userMessage }]
|
||||
}
|
||||
});
|
||||
|
||||
if (response.responseCode === 200) {
|
||||
const data: object = JSON.parse(String(response.result));
|
||||
const choicesArr: object[] = data['choices'] as object[];
|
||||
if (choicesArr && choicesArr.length > 0) {
|
||||
const firstChoice: object = choicesArr[0];
|
||||
const msgObj: object = firstChoice['message'] as object;
|
||||
const assistantMessage: string = String(msgObj['content']);
|
||||
await this.db.saveChatMessage('assistant', assistantMessage);
|
||||
const aiMsg: ChatMessage = { role: 'assistant', content: assistantMessage };
|
||||
this.messages = [...this.messages, aiMsg];
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('HTTP request failed: ' + JSON.stringify(err));
|
||||
}
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
List() {
|
||||
ForEach(this.messages, (msg: ChatMessage) => {
|
||||
ListItem() {
|
||||
Column() {
|
||||
Text(msg.role).fontSize(12).fontColor('#666').width('100%')
|
||||
Text(msg.content).fontSize(16).width('100%').margin({ top: 4 })
|
||||
}
|
||||
.padding(12)
|
||||
.backgroundColor(msg.role === 'user' ? '#E3F2FD' : '#F5F5F5')
|
||||
.borderRadius(8)
|
||||
.margin({ left: 8, right: 8, bottom: 8 })
|
||||
}
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.layoutWeight(1)
|
||||
|
||||
Row() {
|
||||
TextArea({ text: this.inputText, placeholder: '输入消息...' })
|
||||
.layoutWeight(1)
|
||||
.onChange((v: string) => { this.inputText = v; })
|
||||
Button('发送')
|
||||
.onClick(() => this.sendMessage())
|
||||
}
|
||||
.width('100%')
|
||||
.padding(8)
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
}
|
||||
22
harmony/entry/src/main/ets/pages/GraphPage.ets
Normal file
22
harmony/entry/src/main/ets/pages/GraphPage.ets
Normal file
@ -0,0 +1,22 @@
|
||||
import web_webview from '@ohos.web.webview';
|
||||
import { GraphDatabase } from '../model/GraphDatabase';
|
||||
|
||||
@Component
|
||||
export struct GraphPage {
|
||||
private controller: web_webview.WebviewController = new web_webview.WebviewController();
|
||||
@Prop db: GraphDatabase;
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Web({ src: $rawfile('graph.html'), controller: this.controller })
|
||||
.javaScriptAccess(true)
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.onAppear(() => {
|
||||
this.controller.refresh();
|
||||
})
|
||||
}
|
||||
}
|
||||
35
harmony/entry/src/main/ets/pages/Index.ets
Normal file
35
harmony/entry/src/main/ets/pages/Index.ets
Normal file
@ -0,0 +1,35 @@
|
||||
import { MainPage } from './MainPage';
|
||||
import { SettingsPage } from './SettingsPage';
|
||||
import { GraphDatabase } from '../model/GraphDatabase';
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct Index {
|
||||
@State currentIndex: number = 0;
|
||||
private db: GraphDatabase = new GraphDatabase();
|
||||
|
||||
aboutToAppear() {
|
||||
this.db.init(getContext(this));
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Tabs({ index: this.currentIndex, barPosition: BarPosition.End }) {
|
||||
TabContent() {
|
||||
MainPage({ db: this.db })
|
||||
}
|
||||
.tabBar('🌌 TrulyMEM')
|
||||
|
||||
TabContent() {
|
||||
SettingsPage()
|
||||
}
|
||||
.tabBar('⚙ 设置')
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.onChange((index: number) => { this.currentIndex = index; })
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
}
|
||||
21
harmony/entry/src/main/ets/pages/MainPage.ets
Normal file
21
harmony/entry/src/main/ets/pages/MainPage.ets
Normal file
@ -0,0 +1,21 @@
|
||||
import { GraphDatabase } from '../model/GraphDatabase';
|
||||
import { GraphPage } from './GraphPage';
|
||||
import { ChatPage } from './ChatPage';
|
||||
|
||||
@Component
|
||||
export struct MainPage {
|
||||
@Prop db: GraphDatabase;
|
||||
|
||||
build() {
|
||||
GridRow({ columns: { sm: 1, md: 2, lg: 2 }, gutter: { x: 8, y: 8 } }) {
|
||||
GridCol({ span: { sm: 1, md: 1, lg: 1 } }) {
|
||||
GraphPage({ db: this.db })
|
||||
}
|
||||
GridCol({ span: { sm: 1, md: 1, lg: 1 } }) {
|
||||
ChatPage({ db: this.db })
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
}
|
||||
60
harmony/entry/src/main/ets/pages/SettingsPage.ets
Normal file
60
harmony/entry/src/main/ets/pages/SettingsPage.ets
Normal file
@ -0,0 +1,60 @@
|
||||
import dataPreferences from '@ohos.data.preferences';
|
||||
|
||||
@Component
|
||||
export struct SettingsPage {
|
||||
@State baseUrl: string = '';
|
||||
@State model: string = '';
|
||||
@State apiKey: string = '';
|
||||
private pref?: dataPreferences.Preferences;
|
||||
|
||||
async aboutToAppear() {
|
||||
const ctx = getContext(this);
|
||||
this.pref = await dataPreferences.getPreferences(ctx, 'trulymem_config');
|
||||
this.baseUrl = String(await this.pref.get('base_url', 'https://api.deepseek.com'));
|
||||
this.model = String(await this.pref.get('model', 'deepseek-chat'));
|
||||
this.apiKey = String(await this.pref.get('api_key', ''));
|
||||
}
|
||||
|
||||
async onBaseUrlChange(value: string) {
|
||||
this.baseUrl = value;
|
||||
await this.pref?.put('base_url', value);
|
||||
await this.pref?.flush();
|
||||
}
|
||||
|
||||
async onModelChange(value: string) {
|
||||
this.model = value;
|
||||
await this.pref?.put('model', value);
|
||||
await this.pref?.flush();
|
||||
}
|
||||
|
||||
async onApiKeyChange(value: string) {
|
||||
this.apiKey = value;
|
||||
await this.pref?.put('api_key', value);
|
||||
await this.pref?.flush();
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Text('API 配置').fontSize(24).fontWeight(FontWeight.Bold).margin({ top: 20, bottom: 16 })
|
||||
|
||||
Text('Base URL').fontSize(14).width('100%').margin({ left: 16 })
|
||||
TextInput({ placeholder: 'https://api.deepseek.com', text: this.baseUrl })
|
||||
.onChange((v: string) => { this.onBaseUrlChange(v); })
|
||||
.margin({ left: 16, right: 16, bottom: 12 })
|
||||
|
||||
Text('Model ID').fontSize(14).width('100%').margin({ left: 16 })
|
||||
TextInput({ placeholder: 'deepseek-chat', text: this.model })
|
||||
.onChange((v: string) => { this.onModelChange(v); })
|
||||
.margin({ left: 16, right: 16, bottom: 12 })
|
||||
|
||||
Text('API Key').fontSize(14).width('100%').margin({ left: 16 })
|
||||
TextInput({ placeholder: 'sk-...', text: this.apiKey })
|
||||
.type(InputType.Password)
|
||||
.onChange((v: string) => { this.onApiKeyChange(v); })
|
||||
.margin({ left: 16, right: 16, bottom: 12 })
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.padding(16)
|
||||
}
|
||||
}
|
||||
38
harmony/entry/src/main/module.json5
Normal file
38
harmony/entry/src/main/module.json5
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"module": {
|
||||
"name": "entry",
|
||||
"type": "entry",
|
||||
"description": "$string:module_desc",
|
||||
"mainElement": "EntryAbility",
|
||||
"deviceTypes": ["phone", "tablet", "2in1"],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
"pages": "$profile:main_pages",
|
||||
"abilities": [
|
||||
{
|
||||
"name": "EntryAbility",
|
||||
"srcEntry": "./ets/entryability/EntryAbility.ets",
|
||||
"description": "$string:EntryAbility_desc",
|
||||
"icon": "$media:layered_image",
|
||||
"label": "$string:EntryAbility_label",
|
||||
"startWindowIcon": "$media:startIcon",
|
||||
"startWindowBackground": "$color:start_window_background",
|
||||
"exported": true,
|
||||
"skills": [
|
||||
{
|
||||
"entities": ["entity.system.home"],
|
||||
"actions": ["action.system.home"]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"requestPermissions": [
|
||||
{
|
||||
"name": "ohos.permission.INTERNET"
|
||||
},
|
||||
{
|
||||
"name": "ohos.permission.GET_NETWORK_INFO"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
8
harmony/entry/src/main/resources/base/element/color.json
Normal file
8
harmony/entry/src/main/resources/base/element/color.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
||||
20
harmony/entry/src/main/resources/base/element/string.json
Normal file
20
harmony/entry/src/main/resources/base/element/string.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "app_name",
|
||||
"value": "TrulyMEM"
|
||||
},
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "True Memory Engine"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "TrulyMEM Main Ability"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "TrulyMEM"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">
|
||||
<rect width="200" height="200" rx="30" fill="#6366f1"/>
|
||||
<text x="100" y="130" font-family="Arial" font-size="80" fill="white" text-anchor="middle" font-weight="bold">T</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 313 B |
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">
|
||||
<rect width="200" height="200" rx="20" fill="#6366f1"/>
|
||||
<text x="100" y="130" font-family="Arial" font-size="60" fill="white" text-anchor="middle" font-weight="bold">TM</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 314 B |
@ -0,0 +1,5 @@
|
||||
{
|
||||
"src": [
|
||||
"pages/Index"
|
||||
]
|
||||
}
|
||||
302
harmony/entry/src/main/resources/rawfile/graph.html
Normal file
302
harmony/entry/src/main/resources/rawfile/graph.html
Normal file
@ -0,0 +1,302 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>记忆星图 - TrulyMEM</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body { font-family: 'Courier New', monospace; background: #0a0a1a; color: #ffffff; overflow: hidden; width: 100vw; height: 100vh; }
|
||||
#canvas-container { width: 100%; height: 100%; position: relative; }
|
||||
canvas { display: block; }
|
||||
#stats { position: absolute; top: 20px; left: 20px; background: rgba(10, 10, 26, 0.8); padding: 15px 20px; border-radius: 8px; border: 1px solid rgba(100, 100, 255, 0.3); font-size: 14px; z-index: 100; backdrop-filter: blur(10px); }
|
||||
#stats h3 { margin-bottom: 8px; color: #4488ff; font-size: 16px; }
|
||||
#stats p { margin: 4px 0; color: #aaaacc; }
|
||||
#stats span { color: #ffffff; font-weight: bold; }
|
||||
#node-info { position: absolute; top: 20px; right: 20px; background: rgba(10, 10, 26, 0.9); padding: 15px 20px; border-radius: 8px; border: 1px solid rgba(100, 100, 255, 0.3); font-size: 14px; z-index: 100; display: none; backdrop-filter: blur(10px); max-width: 300px; }
|
||||
#node-info h3 { color: #44ff88; margin-bottom: 8px; font-size: 16px; }
|
||||
#node-info p { margin: 4px 0; color: #aaaacc; }
|
||||
#node-info .label { color: #8888aa; }
|
||||
#loading { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 20px; color: #4488ff; z-index: 200; }
|
||||
#nav { position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%); display: flex; gap: 20px; z-index: 100; }
|
||||
.nav-btn { background: rgba(10, 10, 26, 0.8); border: 1px solid rgba(100, 100, 255, 0.3); color: #aaaacc; padding: 12px 24px; border-radius: 8px; cursor: pointer; font-family: 'Courier New', monospace; font-size: 14px; backdrop-filter: blur(10px); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="canvas-container">
|
||||
<div id="loading">正在加载星图数据...</div>
|
||||
<div id="stats">
|
||||
<h3>🌌 记忆星图</h3>
|
||||
<p>节点: <span id="node-count">0</span></p>
|
||||
<p>边: <span id="edge-count">0</span></p>
|
||||
<p>状态: <span id="status">初始化中...</span></p>
|
||||
</div>
|
||||
<div id="node-info">
|
||||
<h3 id="info-name"></h3>
|
||||
<p><span class="label">类型:</span> <span id="info-type"></span></p>
|
||||
<p><span class="label">提及次数:</span> <span id="info-mentions"></span></p>
|
||||
<p><span class="label">连接数:</span> <span id="info-links"></span></p>
|
||||
</div>
|
||||
<div id="nav">
|
||||
<button class="nav-btn active">🌌 星图</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
||||
<script>
|
||||
let scene, camera, renderer, controls;
|
||||
let nodes = [], edges = [];
|
||||
let nodeMeshes = [], edgeLines = [];
|
||||
let starField, nebulaParticles;
|
||||
let raycaster, mouse;
|
||||
let hoveredNode = null, selectedNode = null;
|
||||
let animationId;
|
||||
let highlightPulse = 0;
|
||||
|
||||
const typeColors = { 'person': 0x4488ff, 'task': 0xff8844, 'ai': 0xaa44ff, 'concept': 0x44ff88, 'object': 0xff4444 };
|
||||
const defaultColor = 0xcccccc;
|
||||
const edgeColors = { '喜欢': 0xff6b6b, '学习': 0x4ecdc4, '属于': 0x45b7d1, '相关': 0x96ceb4, '使用': 0xfeca57, '创建': 0xff9ff3 };
|
||||
const defaultEdgeColor = 0x444466;
|
||||
|
||||
function init() {
|
||||
scene = new THREE.Scene();
|
||||
scene.fog = new THREE.FogExp2(0x0a0a1a, 0.015);
|
||||
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 2000);
|
||||
camera.position.set(0, 30, 60);
|
||||
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
renderer.setClearColor(0x0a0a1a, 1);
|
||||
document.getElementById('canvas-container').appendChild(renderer.domElement);
|
||||
controls = new THREE.OrbitControls(camera, renderer.domElement);
|
||||
controls.enableDamping = true;
|
||||
controls.dampingFactor = 0.05;
|
||||
const ambientLight = new THREE.AmbientLight(0x444466, 0.6);
|
||||
scene.add(ambientLight);
|
||||
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
|
||||
directionalLight.position.set(50, 100, 50);
|
||||
scene.add(directionalLight);
|
||||
raycaster = new THREE.Raycaster();
|
||||
mouse = new THREE.Vector2();
|
||||
createStarField();
|
||||
createNebula();
|
||||
window.addEventListener('resize', onWindowResize);
|
||||
renderer.domElement.addEventListener('mousemove', onMouseMove);
|
||||
renderer.domElement.addEventListener('click', onMouseClick);
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.data.type === 'graph_data') {
|
||||
window.__graphData = event.data.payload;
|
||||
loadGraphData();
|
||||
}
|
||||
});
|
||||
window.parent.postMessage('request_graph_data', '*');
|
||||
animate();
|
||||
}
|
||||
|
||||
function createStarField() {
|
||||
const starCount = 3000;
|
||||
const positions = new Float32Array(starCount * 3);
|
||||
const colors = new Float32Array(starCount * 3);
|
||||
for (let i = 0; i < starCount; i++) {
|
||||
const i3 = i * 3;
|
||||
const radius = 400 + Math.random() * 600;
|
||||
const theta = Math.random() * Math.PI * 2;
|
||||
const phi = Math.acos(2 * Math.random() - 1);
|
||||
positions[i3] = radius * Math.sin(phi) * Math.cos(theta);
|
||||
positions[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
|
||||
positions[i3 + 2] = radius * Math.cos(phi);
|
||||
const colorChoice = Math.random();
|
||||
if (colorChoice < 0.7) {
|
||||
colors[i3] = 0.8 + Math.random() * 0.2;
|
||||
colors[i3 + 1] = 0.8 + Math.random() * 0.2;
|
||||
colors[i3 + 2] = 1.0;
|
||||
} else {
|
||||
colors[i3] = 1.0;
|
||||
colors[i3 + 1] = 0.9 + Math.random() * 0.1;
|
||||
colors[i3 + 2] = 0.8 + Math.random() * 0.2;
|
||||
}
|
||||
}
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
||||
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
|
||||
const material = new THREE.PointsMaterial({ size: 1.5, vertexColors: true, transparent: true, opacity: 0.8, sizeAttenuation: true });
|
||||
starField = new THREE.Points(geometry, material);
|
||||
scene.add(starField);
|
||||
}
|
||||
|
||||
function createNebula() {
|
||||
const nebulaCount = 500;
|
||||
const positions = new Float32Array(nebulaCount * 3);
|
||||
const colors = new Float32Array(nebulaCount * 3);
|
||||
for (let i = 0; i < nebulaCount; i++) {
|
||||
const i3 = i * 3;
|
||||
positions[i3] = (Math.random() - 0.5) * 800;
|
||||
positions[i3 + 1] = (Math.random() - 0.5) * 800;
|
||||
positions[i3 + 2] = (Math.random() - 0.5) * 800;
|
||||
const colorChoice = Math.random();
|
||||
if (colorChoice < 0.33) {
|
||||
colors[i3] = 0.5 + Math.random() * 0.3; colors[i3 + 1] = 0.2 + Math.random() * 0.2; colors[i3 + 2] = 0.7 + Math.random() * 0.3;
|
||||
} else if (colorChoice < 0.66) {
|
||||
colors[i3] = 0.2 + Math.random() * 0.2; colors[i3 + 1] = 0.3 + Math.random() * 0.3; colors[i3 + 2] = 0.8 + Math.random() * 0.2;
|
||||
} else {
|
||||
colors[i3] = 0.7 + Math.random() * 0.3; colors[i3 + 1] = 0.2 + Math.random() * 0.2; colors[i3 + 2] = 0.5 + Math.random() * 0.3;
|
||||
}
|
||||
}
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
||||
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
|
||||
const material = new THREE.PointsMaterial({ size: 8, vertexColors: true, transparent: true, opacity: 0.15, sizeAttenuation: true, blending: THREE.AdditiveBlending });
|
||||
nebulaParticles = new THREE.Points(geometry, material);
|
||||
scene.add(nebulaParticles);
|
||||
}
|
||||
|
||||
window.loadGraphData = function(data) {
|
||||
if (data && data.nodes && data.edges) {
|
||||
nodes = data.nodes.map(n => ({ id: n.id, name: n.label || n.name, type: n.type, mention_count: n.mentions || 1 }));
|
||||
edges = data.edges.map(e => ({ id: e.id, source: e.from || e.source, target: e.to || e.target, relation_type: e.label || e.relation }));
|
||||
document.getElementById('node-count').textContent = nodes.length;
|
||||
document.getElementById('edge-count').textContent = edges.length;
|
||||
document.getElementById('status').textContent = '就绪';
|
||||
createGraphVisualization();
|
||||
document.getElementById('loading').style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function createGraphVisualization() {
|
||||
nodeMeshes.forEach(mesh => scene.remove(mesh));
|
||||
edgeLines.forEach(line => scene.remove(line));
|
||||
nodeMeshes = [];
|
||||
edgeLines = [];
|
||||
if (nodes.length === 0) return;
|
||||
const nodeDegrees = {};
|
||||
nodes.forEach(n => nodeDegrees[n.id] = 0);
|
||||
edges.forEach(e => {
|
||||
nodeDegrees[e.source] = (nodeDegrees[e.source] || 0) + 1;
|
||||
nodeDegrees[e.target] = (nodeDegrees[e.target] || 0) + 1;
|
||||
});
|
||||
const positions = {};
|
||||
const maxDegree = Math.max(...Object.values(nodeDegrees), 1);
|
||||
nodes.forEach((node, i) => {
|
||||
const angle = (i / nodes.length) * Math.PI * 2;
|
||||
const radius = 15 + (nodeDegrees[node.id] / maxDegree) * 35;
|
||||
positions[node.id] = { x: radius * Math.cos(angle), y: (Math.random() - 0.5) * 10, z: radius * Math.sin(angle) };
|
||||
});
|
||||
for (let iter = 0; iter < 50; iter++) {
|
||||
Object.keys(positions).forEach(id1 => {
|
||||
Object.keys(positions).forEach(id2 => {
|
||||
if (id1 >= id2) return;
|
||||
const pos1 = positions[id1], pos2 = positions[id2];
|
||||
const dx = pos1.x - pos2.x, dy = pos1.y - pos2.y, dz = pos1.z - pos2.z;
|
||||
const dist = Math.sqrt(dx*dx + dy*dy + dz*dz) + 0.1;
|
||||
if (dist < 10) {
|
||||
const force = 0.1 / dist;
|
||||
pos1.x += (dx/dist)*force; pos1.y += (dy/dist)*force; pos1.z += (dz/dist)*force;
|
||||
pos2.x -= (dx/dist)*force; pos2.y -= (dy/dist)*force; pos2.z -= (dz/dist)*force;
|
||||
}
|
||||
});
|
||||
});
|
||||
edges.forEach(edge => {
|
||||
const pos1 = positions[edge.source], pos2 = positions[edge.target];
|
||||
if (!pos1 || !pos2) return;
|
||||
const dx = pos2.x - pos1.x, dy = pos2.y - pos1.y, dz = pos2.z - pos1.z;
|
||||
const dist = Math.sqrt(dx*dx + dy*dy + dz*dz) + 0.1;
|
||||
if (dist > 15) {
|
||||
const force = 0.05;
|
||||
pos1.x += (dx/dist)*force; pos1.y += (dy/dist)*force; pos1.z += (dz/dist)*force;
|
||||
pos2.x -= (dx/dist)*force; pos2.y -= (dy/dist)*force; pos2.z -= (dz/dist)*force;
|
||||
}
|
||||
});
|
||||
}
|
||||
nodes.forEach(node => {
|
||||
const pos = positions[node.id];
|
||||
if (!pos) return;
|
||||
const radius = 0.4 + Math.min(node.mention_count * 0.15, 1.5);
|
||||
const color = typeColors[node.type] || defaultColor;
|
||||
const geometry = new THREE.SphereGeometry(radius, 16, 12);
|
||||
const material = new THREE.MeshPhongMaterial({ color: color, emissive: color, emissiveIntensity: 0.5 + Math.min(node.mention_count * 0.05, 0.3), shininess: 30 });
|
||||
const sphere = new THREE.Mesh(geometry, material);
|
||||
sphere.position.set(pos.x, pos.y, pos.z);
|
||||
sphere.userData = { nodeId: node.id, nodeData: node };
|
||||
scene.add(sphere);
|
||||
nodeMeshes.push(sphere);
|
||||
});
|
||||
edges.forEach(edge => {
|
||||
const pos1 = positions[edge.source], pos2 = positions[edge.target];
|
||||
if (!pos1 || !pos2) return;
|
||||
const color = edgeColors[edge.relation_type] || defaultEdgeColor;
|
||||
const geometry = new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(pos1.x, pos1.y, pos1.z), new THREE.Vector3(pos2.x, pos2.y, pos2.z)]);
|
||||
const material = new THREE.LineBasicMaterial({ color: color, transparent: true, opacity: 0.4, linewidth: 1 });
|
||||
const line = new THREE.Line(geometry, material);
|
||||
line.userData = { edgeId: edge.id, edgeData: edge };
|
||||
scene.add(line);
|
||||
edgeLines.push(line);
|
||||
});
|
||||
const allPositions = Object.values(positions);
|
||||
if (allPositions.length > 0) {
|
||||
let maxDist = 0;
|
||||
allPositions.forEach(pos => { maxDist = Math.max(maxDist, Math.sqrt(pos.x*pos.x + pos.y*pos.y + pos.z*pos.z)); });
|
||||
camera.position.set(maxDist * 2.2, maxDist * 1.5, maxDist * 2.2);
|
||||
controls.target.set(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseMove(event) {
|
||||
const rect = renderer.domElement.getBoundingClientRect();
|
||||
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
|
||||
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
|
||||
raycaster.setFromCamera(mouse, camera);
|
||||
const intersects = raycaster.intersectObjects(nodeMeshes);
|
||||
if (intersects.length > 0) {
|
||||
const node = intersects[0].object;
|
||||
if (hoveredNode !== node) {
|
||||
if (hoveredNode) hoveredNode.scale.set(1, 1, 1);
|
||||
hoveredNode = node;
|
||||
node.scale.set(1.2, 1.2, 1.2);
|
||||
showNodeInfo(node.userData.nodeData);
|
||||
}
|
||||
} else {
|
||||
if (hoveredNode) { hoveredNode.scale.set(1, 1, 1); hoveredNode = null; hideNodeInfo(); }
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseClick(event) {
|
||||
raycaster.setFromCamera(mouse, camera);
|
||||
const intersects = raycaster.intersectObjects(nodeMeshes);
|
||||
if (intersects.length > 0) {
|
||||
const node = intersects[0].object;
|
||||
if (selectedNode === node) { selectedNode = null; document.getElementById('node-info').style.display = 'none'; }
|
||||
else { selectedNode = node; showNodeInfo(node.userData.nodeData, true); }
|
||||
}
|
||||
}
|
||||
|
||||
function showNodeInfo(nodeData, isClick = false) {
|
||||
document.getElementById('info-name').textContent = nodeData.name;
|
||||
document.getElementById('info-type').textContent = nodeData.type;
|
||||
document.getElementById('info-mentions').textContent = nodeData.mention_count;
|
||||
const linkCount = edges.filter(e => e.source === nodeData.id || e.target === nodeData.id).length;
|
||||
document.getElementById('info-links').textContent = linkCount;
|
||||
if (isClick) document.getElementById('node-info').style.display = 'block';
|
||||
}
|
||||
|
||||
function hideNodeInfo() { if (!selectedNode) document.getElementById('node-info').style.display = 'none'; }
|
||||
|
||||
function onWindowResize() {
|
||||
camera.aspect = window.innerWidth / window.innerHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
}
|
||||
|
||||
function animate() {
|
||||
animationId = requestAnimationFrame(animate);
|
||||
const time = Date.now() * 0.001;
|
||||
highlightPulse = (highlightPulse + 0.02) % (Math.PI * 2);
|
||||
controls.update();
|
||||
if (starField) starField.rotation.y += 0.0001;
|
||||
if (hoveredNode) { const pulse = 1 + Math.sin(highlightPulse * 3) * 0.05; hoveredNode.scale.set(pulse * 1.2, pulse * 1.2, pulse * 1.2); }
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
init();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
23
harmony/hvigor/hvigor-config.json5
Normal file
23
harmony/hvigor/hvigor-config.json5
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"modelVersion": "5.0.5",
|
||||
"dependencies": {
|
||||
},
|
||||
"execution": {
|
||||
// "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | false ]. Default: "normal" */
|
||||
// "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */
|
||||
// "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */
|
||||
// "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */
|
||||
// "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */
|
||||
// "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */
|
||||
},
|
||||
"logging": {
|
||||
// "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
|
||||
},
|
||||
"debugging": {
|
||||
// "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */
|
||||
},
|
||||
"nodeOptions": {
|
||||
// "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/
|
||||
// "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/
|
||||
}
|
||||
}
|
||||
6
harmony/hvigorfile.ts
Normal file
6
harmony/hvigorfile.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { appTasks } from '@ohos/hvigor-ohos-plugin';
|
||||
|
||||
export default {
|
||||
system: appTasks,
|
||||
plugins: []
|
||||
};
|
||||
2
harmony/local.properties
Normal file
2
harmony/local.properties
Normal file
@ -0,0 +1,2 @@
|
||||
hwsdk.dir=/home/program/tools/command-line-tools/sdk/default
|
||||
sdk.dir=/home/program/tools/command-line-tools/sdk/default
|
||||
10
harmony/oh-package.json5
Normal file
10
harmony/oh-package.json5
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"modelVersion": "5.0.5",
|
||||
"description": "Please describe the basic information.",
|
||||
"dependencies": {
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ohos/hypium": "1.0.24",
|
||||
"@ohos/hamock": "1.0.0"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
{
|
||||
"app": {
|
||||
"bundleName": "com.example.rconmc",
|
||||
"debug": true,
|
||||
"versionCode": 1000000,
|
||||
"versionName": "1.0.0",
|
||||
"minAPIVersion": 60001021,
|
||||
"targetAPIVersion": 60001021,
|
||||
"apiReleaseType": "Release",
|
||||
"targetMinorAPIVersion": 0,
|
||||
"targetPatchAPIVersion": 0,
|
||||
"compileSdkVersion": "6.0.2.130",
|
||||
"compileSdkType": "HarmonyOS",
|
||||
"appEnvironments": [],
|
||||
"bundleType": "app",
|
||||
"buildMode": "debug"
|
||||
},
|
||||
"module": {
|
||||
"name": "librcon",
|
||||
"type": "har",
|
||||
"requestPermissions": [],
|
||||
"deviceTypes": [
|
||||
"default",
|
||||
"tablet",
|
||||
"2in1"
|
||||
],
|
||||
"packageName": "librcon",
|
||||
"installationFree": false
|
||||
}
|
||||
}
|
||||
17
harmony/trulymem-core/BuildProfile.ets
Normal file
17
harmony/trulymem-core/BuildProfile.ets
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Use these variables when you tailor your ArkTS code. They must be of the const type.
|
||||
*/
|
||||
export const HAR_VERSION = '1.0.0';
|
||||
export const BUILD_MODE_NAME = 'debug';
|
||||
export const DEBUG = true;
|
||||
export const TARGET_NAME = 'default';
|
||||
|
||||
/**
|
||||
* BuildProfile Class is used only for compatibility purposes.
|
||||
*/
|
||||
export default class BuildProfile {
|
||||
static readonly HAR_VERSION = HAR_VERSION;
|
||||
static readonly BUILD_MODE_NAME = BUILD_MODE_NAME;
|
||||
static readonly DEBUG = DEBUG;
|
||||
static readonly TARGET_NAME = TARGET_NAME;
|
||||
}
|
||||
2
harmony/trulymem-core/Index.ets
Normal file
2
harmony/trulymem-core/Index.ets
Normal file
@ -0,0 +1,2 @@
|
||||
// TrulyMEM Core - 导出核心功能
|
||||
export { GraphDatabase } from './src/main/ets/GraphDatabase';
|
||||
41
harmony/trulymem-core/build-profile.json5
Normal file
41
harmony/trulymem-core/build-profile.json5
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"apiType": "stageMode",
|
||||
"buildOption": {
|
||||
"resOptions": {
|
||||
"copyCodeResource": {
|
||||
"enable": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"buildOptionSet": [
|
||||
{
|
||||
"name": "release",
|
||||
"arkOptions": {
|
||||
"obfuscation": {
|
||||
"ruleOptions": {
|
||||
"enable": false,
|
||||
"files": [
|
||||
"./obfuscation-rules.txt"
|
||||
]
|
||||
},
|
||||
"consumerFiles": [
|
||||
"./consumer-rules.txt"
|
||||
]
|
||||
}
|
||||
},
|
||||
"resOptions": {
|
||||
"copyCodeResource": {
|
||||
"enable": false
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
"targets": [
|
||||
{
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"name": "ohosTest"
|
||||
}
|
||||
]
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user