Skip to content
Draft
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
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,5 @@
/.clang-tidy
**/.test
/.appanalyzer
build-profile.json5
agconnect-services.json
HdsMiniBarButton.ets
.deadliner-core/
40 changes: 40 additions & 0 deletions build-profile.json5
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"app": {
"products": [
{
"name": "default",
"targetSdkVersion": "26.0.0",
"compatibleSdkVersion": "6.0.0(20)",
"runtimeOS": "HarmonyOS",
"buildOption": {
"strictMode": {
"caseSensitiveCheck": true,
"useNormalizedOHMUrl": true
}
}
}
],
"buildModeSet": [
{
"name": "debug"
},
{
"name": "release"
}
]
},
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [
{
"name": "default",
"applyToProducts": [
"default"
]
}
]
}
]
}
27 changes: 27 additions & 0 deletions entry/build-profile.json5
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"apiType": "stageMode",
"buildOption": {},
"buildOptionSet": [
{
"name": "release",
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": false,
"files": [
"./obfuscation-rules.txt"
]
}
}
}
}
],
"targets": [
{
"name": "default"
},
{
"name": "ohosTest"
}
]
}
2 changes: 1 addition & 1 deletion entry/oh-package-lock.json5

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 23 additions & 1 deletion entry/src/main/ets/AppTheme.ets
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ export class DeadlinerColors implements CustomColors {

// 品牌色
brand: ResourceColor
primary: ResourceColor
onPrimary: ResourceColor = $r('app.color.font_on_primary')
container: ResourceColor = $r('app.color.background_secondary')

// 告警/确认
warning: ResourceColor = $r('app.color.warning')
Expand All @@ -15,32 +18,51 @@ export class DeadlinerColors implements CustomColors {
// 文本
fontPrimary: ResourceColor = $r('app.color.font_primary')
fontSecondary: ResourceColor = $r('app.color.font_secondary')
fontTertiary: ResourceColor = $r('app.color.font_tertiary')
fontFourth: ResourceColor = $r('app.color.font_fourth')
fontEmphasize: ResourceColor = $r('app.color.font_emphasize')
fontOnPrimary: ResourceColor = $r('app.color.font_on_primary')

// 图标
iconPrimary: ResourceColor = $r('app.color.icon_primary')
iconSecondary: ResourceColor = $r('app.color.icon_secondary')
iconTertiary: ResourceColor = $r('app.color.icon_tertiary')
iconFourth: ResourceColor = $r('app.color.icon_fourth')
iconEmphasize: ResourceColor = $r('app.color.icon_emphasize')
iconOnPrimary: ResourceColor = $r('app.color.icon_on_primary')

// 背景
backgroundPrimary: ResourceColor
backgroundSecondary: ResourceColor = $r('app.color.background_secondary')
backgroundTertiary: ResourceColor = $r('app.color.background_tertiary')
backgroundFourth: ResourceColor = $r('app.color.background_emphasize')
backgroundEmphasize: ResourceColor = $r('app.color.background_emphasize')

// 组件表面
compBackgroundPrimary: ResourceColor = $r('app.color.background_secondary')
compBackgroundSecondary: ResourceColor = $r('app.color.background_tertiary')
compBackgroundTertiary: ResourceColor = $r('app.color.background_primary_50')
compBackgroundEmphasize: ResourceColor

// 分割线
compDivider: ResourceColor = $r('app.color.comp_divider')

// 通用交互
interactiveActive: ResourceColor = $r('app.color.interactive_active')
interactiveSelect: ResourceColor = $r('app.color.interactive_select')
interactivePressed: ResourceColor = $r('app.color.interactive_pressed')
interactiveHover: ResourceColor = $r('app.color.interactive_select')
interactiveFocus: ResourceColor
interactiveClick: ResourceColor = $r('app.color.interactive_pressed')

// 构造函数:接收当前的 ITheme 配置
constructor(theme: ITheme) {
this.brand = theme.brand
this.primary = theme.brand
this.alert = theme.brand // 复用 brand
this.backgroundPrimary = theme.bgPrimary
this.compBackgroundEmphasize = theme.brand
this.interactiveFocus = theme.brand
}
}

Expand All @@ -50,4 +72,4 @@ export class DeadlinerTheme implements CustomTheme {
constructor(theme: ITheme) {
this.colors = new DeadlinerColors(theme)
}
}
}
8 changes: 7 additions & 1 deletion entry/src/main/ets/common/layout/AppBreakpoints.ets
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ export enum AppBreakpoint {
}

export const APP_BREAKPOINT_STORAGE_KEY: string = 'appBreakpoint';
export const APP_BREAKPOINT_DEFAULT: AppBreakpoint = AppBreakpoint.MD;
// Compact is the safest first-frame fallback before the window callback arrives.
export const APP_BREAKPOINT_DEFAULT: AppBreakpoint = AppBreakpoint.SM;

export const APP_BREAKPOINT_ORDER: AppBreakpoint[] = [
AppBreakpoint.SM,
Expand All @@ -19,6 +20,7 @@ export class AppBreakpointUtils {
static readonly MD_MIN_WIDTH: number = 600;
static readonly LG_MIN_WIDTH: number = 840;
static readonly XL_MIN_WIDTH: number = 1320;
static readonly COMPACT_HEIGHT_MAX: number = 480;

static mediaCondition(breakpoint: AppBreakpoint): string {
switch (breakpoint) {
Expand Down Expand Up @@ -51,4 +53,8 @@ export class AppBreakpointUtils {
static isWide(breakpoint: string): boolean {
return breakpoint === AppBreakpoint.LG || breakpoint === AppBreakpoint.XL;
}

static isCompactHeight(heightVp: number): boolean {
return heightVp > 0 && heightVp <= AppBreakpointUtils.COMPACT_HEIGHT_MAX;
}
}
35 changes: 22 additions & 13 deletions entry/src/main/ets/common/local/LocalValues.ets
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { preferences } from '@kit.ArkData';
import { SettingsConstants as C } from './SettingsConstants';
import { SecureStorage } from './SecureStorage';
import { MainButtonType } from './LocalModels';
import { deviceInfo } from '@kit.BasicServicesKit';
import { HarmonyOSCapabilities } from '../platform/HarmonyOSCapabilities';

interface WebDavAuthInterface {
user: string;
Expand Down Expand Up @@ -153,13 +153,14 @@ export class LocalValues {
const showPaperTalkShare = await this.pref.get(C.KEY_SHOW_PAPERTALK_SHARE, true);
AppStorage.setOrCreate(C.KEY_SHOW_PAPERTALK_SHARE, showPaperTalkShare);

const enableApi23 = await this.pref.get(C.KEY_ENABLE_API23, true);
AppStorage.setOrCreate(C.KEY_ENABLE_API23, enableApi23);
const immersiveMaterialPreference = await this.pref.get(C.KEY_ENABLE_IMMERSIVE_MATERIAL, true) as boolean;
const immersiveMaterial = HarmonyOSCapabilities.supportsImmersiveMaterial() && immersiveMaterialPreference;
AppStorage.setOrCreate(C.KEY_ENABLE_IMMERSIVE_MATERIAL, immersiveMaterial);

const materialLevel = await this.pref.get(C.KEY_API23_MATERIAL_LEVEL, 'EXQUISITE');
AppStorage.setOrCreate(C.KEY_API23_MATERIAL_LEVEL, materialLevel)
const materialLevel = await this.pref.get(C.KEY_MATERIAL_LEVEL, 'ADAPTIVE');
AppStorage.setOrCreate(C.KEY_MATERIAL_LEVEL, materialLevel)

const minibar = await this.pref.get(C.KEY_SHOW_MINIBAR, (deviceInfo.distributionOSApiVersion >= 60100));
const minibar = await this.pref.get(C.KEY_SHOW_MINIBAR, HarmonyOSCapabilities.supportsImmersiveMaterial());
AppStorage.setOrCreate(C.KEY_SHOW_MINIBAR, minibar);

const experimentalComponents = await this.pref.get(C.KEY_EXPERIMENTAL_COMPONENTS, true);
Expand Down Expand Up @@ -679,12 +680,20 @@ export class LocalValues {
await this.setValue(C.KEY_TOMBSTONE_RETENTION_DAYS, days);
}

isImmersiveMaterialEnabled(): boolean {
return AppStorage.get(C.KEY_ENABLE_IMMERSIVE_MATERIAL) ?? true;
}

async setImmersiveMaterialEnabled(enable: boolean): Promise<void> {
await this.setValue(C.KEY_ENABLE_IMMERSIVE_MATERIAL, enable);
}

getApi23Enable(): boolean {
return AppStorage.get(C.KEY_ENABLE_API23) ?? true;
return this.isImmersiveMaterialEnabled();
}

async setApi23Enable(enable: boolean) {
await this.setValue(C.KEY_ENABLE_API23, enable);
async setApi23Enable(enable: boolean): Promise<void> {
await this.setImmersiveMaterialEnabled(enable);
}

getExperimentalComponents(): boolean {
Expand All @@ -704,21 +713,21 @@ export class LocalValues {
}

getMaterialLevel(): string {
return AppStorage.get(C.KEY_API23_MATERIAL_LEVEL) ?? 'EXQUISITE';
return AppStorage.get(C.KEY_MATERIAL_LEVEL) ?? 'ADAPTIVE';
}

async setMaterialLevel(level: string) {
const levels = ['ADAPTIVE', 'SMOOTH', 'GENTLE', 'EXQUISITE'];
const actual = (levels.includes(level)) ? level : 'ADAPTIVE';
await this.setValue(C.KEY_API23_MATERIAL_LEVEL, actual);
await this.setValue(C.KEY_MATERIAL_LEVEL, actual);
}

getMiniBar(): boolean {
return AppStorage.get(C.KEY_SHOW_MINIBAR) ?? (deviceInfo.distributionOSApiVersion >= 60100);
return AppStorage.get(C.KEY_SHOW_MINIBAR) ?? HarmonyOSCapabilities.supportsImmersiveMaterial();
}

async setMiniBar(enable: boolean) {
if (deviceInfo.distributionOSApiVersion >= 60100) {
if (HarmonyOSCapabilities.supportsImmersiveMaterial()) {
await this.setValue(C.KEY_SHOW_MINIBAR, enable);
return;
}
Expand Down
7 changes: 5 additions & 2 deletions entry/src/main/ets/common/local/SettingsConstants.ets
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,11 @@ export class SettingsConstants {
static readonly KEY_AUTO_ARCHIVE_DAYS = 'auto_archive_days';
static readonly KEY_TOMBSTONE_RETENTION_DAYS = 'tombstone_retention_days';

static readonly KEY_ENABLE_API23 = 'enable_api23';
static readonly KEY_API23_MATERIAL_LEVEL = 'material_level';
// Keep the persisted keys stable while exposing version-neutral names in code.
static readonly KEY_ENABLE_IMMERSIVE_MATERIAL = 'enable_api23';
static readonly KEY_MATERIAL_LEVEL = 'material_level';
static readonly KEY_ENABLE_API23 = SettingsConstants.KEY_ENABLE_IMMERSIVE_MATERIAL;
static readonly KEY_API23_MATERIAL_LEVEL = SettingsConstants.KEY_MATERIAL_LEVEL;
static readonly KEY_EXPERIMENTAL_COMPONENTS = 'experimental_components';

static readonly KEY_OVERVIEW_CARD_ORDER = 'overview_card_order';
Expand Down
20 changes: 20 additions & 0 deletions entry/src/main/ets/common/platform/HarmonyOSCapabilities.ets
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { deviceInfo } from '@kit.BasicServicesKit';

/**
* HarmonyOS UI capability gates.
*
* Use the public SDK API level instead of parsing distribution version strings.
* This keeps preview, emulator, phone, tablet and 2-in-1 behavior consistent.
*/
export class HarmonyOSCapabilities {
static readonly IMMERSIVE_MATERIAL_API: number = 23;
static readonly HARMONYOS_7_API: number = 26;

static supportsImmersiveMaterial(): boolean {
return deviceInfo.sdkApiVersion >= HarmonyOSCapabilities.IMMERSIVE_MATERIAL_API;
}

static isHarmonyOS7OrLater(): boolean {
return deviceInfo.sdkApiVersion >= HarmonyOSCapabilities.HARMONYOS_7_API;
}
}
21 changes: 0 additions & 21 deletions entry/src/main/ets/common/style/MaterialLevel.ets
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,3 @@ export function getHdsMaterialLevel(level?: string): hdsMaterial.MaterialLevel {
return hdsMaterial.MaterialLevel.ADAPTIVE
}
}

export function getHdsMaterialLevelRaw(level?: string): number {
if (!level) {
level = LocalValues.getInstance().getMaterialLevel()
}

console.log(`Material Level ${level}`)

switch (level) {
case 'ADAPTIVE':
return 10
case 'SMOOTH':
return 2
case 'GENTLE':
return 1
case 'EXQUISITE':
return 0
default:
return 10
}
}
7 changes: 4 additions & 3 deletions entry/src/main/ets/common/style/NavStyles.ets
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { LengthMetrics } from '@kit.ArkUI';
import { hdsMaterial, HdsNavigationTitleBarStyle, ScrollEffectType, TitleBarStyleOptions } from '@kit.UIDesignKit';
import { ThemeManager } from '../theme/ThemeManager';
import { deviceInfo } from '@kit.BasicServicesKit';
import { LocalValues } from '../local/LocalValues';
import { getHdsMaterialLevel } from './MaterialLevel';
import { HarmonyOSCapabilities } from '../platform/HarmonyOSCapabilities';

/**
* 获取统一的沉浸式标题栏样式配置
Expand All @@ -16,7 +16,8 @@ export function getImmersiveTitleBarStyle(
disableMaterial: boolean = false,
level?: string,
) : TitleBarStyleOptions {
if (deviceInfo.distributionOSApiVersion >= 60100 && LocalValues.getInstance().getApi23Enable()) {
if (HarmonyOSCapabilities.supportsImmersiveMaterial() &&
LocalValues.getInstance().isImmersiveMaterialEnabled()) {
return {
scrollEffectOpts: {
// enableScrollEffect: !isWideScreen,
Expand Down Expand Up @@ -81,4 +82,4 @@ export function getImmersiveTitleBarStyle(
},
};
}
}
}
5 changes: 5 additions & 0 deletions entry/src/main/ets/common/theme/ThemeManager.ets
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,11 @@ export class ThemeManager {
}
}

/** Reapply after ArkUI content has been attached to the window. */
static reapplySystemTheme(): void {
ThemeManager.applySystemTheme(ThemeManager.getCurrentTheme());
}

// =================================================================
// 公共 API (切换逻辑)
// =================================================================
Expand Down
Loading