Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/apps/desktop/src/api/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2212,6 +2212,12 @@ pub async fn reveal_in_explorer(
))
}
};
#[cfg(target_env = "ohos")]
{
use crate::ohos::ohos_file_system::reveal_in_oh_explorer;
let _ = reveal_in_oh_explorer(path.to_string_lossy().to_string());
return Ok(());
}
if !path.exists() {
return Err(format!("Path does not exist: {}", request.path));
}
Expand Down
29 changes: 28 additions & 1 deletion src/apps/desktop/src/api/ohos/ohos_file_system.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
use bitfun_core::util::open_dialog_file;
use bitfun_core::util::{JS_THREADSAFE_FUNCTION, open_dialog_file};
use napi_ohos::threadsafe_function::ThreadsafeFunctionCallMode;
#[tauri::command]
pub async fn open_oh_file_dialog() -> Result<String, String> {
open_dialog_file().await
}

#[tauri::command]
pub async fn set_theme_mode(theme: String) -> Result<(), String> {
let function = {
let lock = JS_THREADSAFE_FUNCTION.read();
lock.get("set_theme_mode").cloned()
};
let Some(function) = function else {
return Err("The Arkts has not register the function".to_owned());
};
function.call(Ok(theme),ThreadsafeFunctionCallMode::NonBlocking);
Ok(())
}

#[tauri::command]
pub fn reveal_in_oh_explorer(path: String) -> Result<(), String> {
let function = {
let lock = JS_THREADSAFE_FUNCTION.read();
lock.get("reveal_in_explorer").cloned()
};
let Some(function) = function else {
return Err("The Arkts has not register the function".to_owned());
};
function.call(Ok(path),ThreadsafeFunctionCallMode::NonBlocking);
Ok(())
}
4 changes: 0 additions & 4 deletions src/apps/desktop/src/api/ohos/window.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
use crate::AppState;
use bitfun_core::util::JS_THREADSAFE_FUNCTION;
use log::error;
use napi_ohos::threadsafe_function::ThreadsafeFunctionCallMode;
use std::sync::mpsc::channel;
use tauri::State;

#[tauri::command]
pub fn handle_min_window() -> Result<(), String> {
Expand Down
3 changes: 2 additions & 1 deletion src/apps/desktop/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use tauri::Manager;
// Re-export API
pub use api::*;

use crate::ohos::ohos_file_system::open_oh_file_dialog;
use crate::ohos::ohos_file_system::{open_oh_file_dialog, set_theme_mode};
use crate::ohos::window::{
close_window,handle_max_window,handle_min_window,handle_restore_window,window_is_maximized,
window_is_minimized, window_start_dragging
Expand Down Expand Up @@ -792,6 +792,7 @@ pub async fn _run() {
window_is_minimized,
window_start_dragging,
close_window,
set_theme_mode,

])
.run(tauri::generate_context!());
Expand Down
57 changes: 46 additions & 11 deletions src/apps/vcoder/entry/src/main/ets/entryability/EntryAbility.ets
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import {
abilityAccessCtrl, AbilityConstant, common, Permissions, Want
abilityAccessCtrl,
AbilityConstant,
common,
ConfigurationConstant,
Permissions,
Want
} from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
Expand Down Expand Up @@ -119,6 +124,37 @@ export default class EntryAbility extends RustAbility {
});
return '';
});
setTimeout(() => {
windowStage.getMainWindow((err, data) => {
data.setWindowDecorHeight(32)
data.setWindowDecorVisible(false);
})
}, 40)
RustModule.registerArktsFunction('reveal_in_explorer', async (err: Error, arg: string): Promise<string> => {
const path = arg.replace('file://', 'file://docs');
const want: Want = {
bundleName: 'com.huawei.hmos.filemanager',
abilityName: 'MainAbility',
parameters: {
fileUri: path
}
};
const context = getContext(this) as common.UIAbilityContext;
try {
await context.startAbility(want)
} catch (err) {
hilog.error(201, 'vnext', `reveal in explorer failed ${JSON.stringify(err)}`)
}
return '';
});
RustModule.registerArktsFunction('set_theme_mode', async (err: Error, arg: string): Promise<string> => {
if (arg === 'bitfun-light' || arg === 'bitfun-china-style') {
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT)
} else {
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_DARK)
}
return '';
});
return super.onWindowStageCreate(windowStage);
}

Expand All @@ -129,16 +165,15 @@ export default class EntryAbility extends RustAbility {

private sendOnlyCallback = (sharableTable: harmonyShare.SharableTarget) => {
if (this.remote_url.length == 0) {
let content = this.remote_url;
let shareData: systemShare.SharedData = new systemShare.SharedData({
utd: uniformTypeDescriptor.UniformDataType.HYPERLINK,
content,
title: "Bitfun",
description: "Phone",
});
sharableTable.share(shareData)
}
else {
let content = this.remote_url;
let shareData: systemShare.SharedData = new systemShare.SharedData({
utd: uniformTypeDescriptor.UniformDataType.HYPERLINK,
content,
title: "Bitfun",
description: "Phone",
});
sharableTable.share(shareData)
} else {
hilog.error(DOMAIN, 'vnext', 'sendOnlyCallback error: remote url is empty');
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/web-ui/src/app/components/NavBar/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { PanelLeftIcon } from '../TitleBar/PanelIcons';
import { createLogger } from '@/shared/utils/logger';
import { isMacOSDesktopRuntime, supportsNativeWindowDragging } from '@/infrastructure/runtime';
import './NavBar.scss';
import { workspaceAPI } from '@/infrastructure';

const log = createLogger('NavBar');

Expand Down Expand Up @@ -65,8 +66,7 @@ const NavBar: React.FC<NavBarProps> = ({

void (async () => {
try {
const { getCurrentWindow } = await import('@tauri-apps/api/window');
await getCurrentWindow().startDragging();
await workspaceAPI.window_start_dragging();
} catch (error) {
log.debug('startDragging failed', error);
}
Expand Down
4 changes: 2 additions & 2 deletions src/web-ui/src/app/components/SceneBar/SceneBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { useI18n } from '@/infrastructure/i18n/hooks/useI18n';
import { createLogger } from '@/shared/utils/logger';
import { supportsNativeWindowDragging } from '@/infrastructure/runtime';
import './SceneBar.scss';
import { workspaceAPI } from '@/infrastructure';

const log = createLogger('SceneBar');

Expand Down Expand Up @@ -66,8 +67,7 @@ const SceneBar: React.FC<SceneBarProps> = ({

void (async () => {
try {
const { getCurrentWindow } = await import('@tauri-apps/api/window');
await getCurrentWindow().startDragging();
await workspaceAPI.window_start_dragging();
} catch (error) {
log.debug('startDragging failed', error);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
*/

import React from 'react';
import { useTranslation } from 'react-i18next';
import { Tooltip } from '../Tooltip';
import './WindowControls.scss';

export interface WindowControlsProps extends React.HTMLAttributes<HTMLDivElement> {
Expand All @@ -29,122 +27,7 @@ export interface WindowControlsProps extends React.HTMLAttributes<HTMLDivElement
* Window control button component
* Provides a unified window control UI (minimize, maximize, close)
*/
export const WindowControls: React.FC<WindowControlsProps> = ({
onMinimize,
onMaximize,
onClose,
showMinimize = true,
showMaximize = true,
showClose = true,
disabled = false,
isMaximized = false,
minimizeIcon,
maximizeIcon,
restoreIcon,
closeIcon,
className = '',
'data-testid-minimize': testIdMinimize,
'data-testid-maximize': testIdMaximize,
'data-testid-close': testIdClose,
...props
}) => {
const { t } = useTranslation('common');
const defaultMinimizeIcon = (
<svg width="10" height="10" viewBox="0 0 14 14" fill="none">
<line x1="3" y1="7" x2="11" y2="7" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
</svg>
);

const defaultMaximizeIcon = (
<svg width="10" height="10" viewBox="0 0 12 12" fill="none">
<rect x="2" y="2" width="8" height="8" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
);

const defaultRestoreIcon = (
<svg width="10" height="10" viewBox="0 0 12 12" fill="none">
<path d="M4 4 L4 1.5 Q4 1 4.5 1 L10.5 1 Q11 1 11 1.5 L11 7.5 Q11 8 10.5 8 L8 8" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
<rect x="1" y="4" width="7" height="7" rx="0.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
</svg>
);

const defaultCloseIcon = (
<svg width="10" height="10" viewBox="0 0 14 14" fill="none">
<line x1="3" y1="3" x2="11" y2="11" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
<line x1="11" y1="3" x2="3" y2="11" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
</svg>
);

return (
<div
className={`window-controls ${className}`}
{...props}
>
{showMinimize && (
<Tooltip content={t('window.minimize')} placement="bottom">
<button
className="window-controls__btn window-controls__btn--minimize"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
if (onMinimize && !disabled) {
onMinimize();
}
}}
disabled={disabled}
aria-label={t('window.minimize')}
type="button"
data-testid={testIdMinimize}
>
{minimizeIcon || defaultMinimizeIcon}
</button>
</Tooltip>
)}

{showMaximize && (
<Tooltip content={isMaximized ? t('window.restore') : t('window.maximize')} placement="bottom">
<button
className="window-controls__btn window-controls__btn--maximize"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
if (onMaximize && !disabled) {
onMaximize();
}
}}
disabled={disabled}
aria-label={isMaximized ? t('window.restore') : t('window.maximize')}
type="button"
data-testid={testIdMaximize}
>
{isMaximized
? (restoreIcon || defaultRestoreIcon)
: (maximizeIcon || defaultMaximizeIcon)
}
</button>
</Tooltip>
)}

{showClose && (
<Tooltip content={t('window.close')} placement="bottom">
<button
className="window-controls__btn window-controls__btn--close"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
if (onClose && !disabled) {
onClose();
}
}}
disabled={disabled}
aria-label={t('window.close')}
type="button"
data-testid={testIdClose}
>
{closeIcon || defaultCloseIcon}
</button>
</Tooltip>
)}
</div>
);
export const WindowControls: React.FC<WindowControlsProps> = (
) => {
return ( <div style={{width: 128}}/> );
};
Loading
Loading