diff --git a/global.d.ts b/global.d.ts deleted file mode 100644 index 67bf093..0000000 --- a/global.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -interface WebActivity { - start(): Promise; - cancel(): void; -} - -declare var WebActivity: { - prototype: WebActivity; - new(name: string, data?: any): WebActivity; -}; \ No newline at end of file diff --git a/src/components/brightness-slider/brightness-slider.ts b/src/components/brightness-slider/brightness-slider.ts new file mode 100644 index 0000000..ebd7f84 --- /dev/null +++ b/src/components/brightness-slider/brightness-slider.ts @@ -0,0 +1,193 @@ +import {html, css, LitElement, HTMLTemplateResult} from 'lit' +import {customElement, property, query} from 'lit/decorators.js' +@customElement('brightness-slider') +export class BrightnessSlider extends LitElement { + @query('.progress') progress!: HTMLDivElement + @query('.sliderBar') sliderBar!: HTMLDivElement + @property({type: String}) id = '' + @property({type: String}) _coverLen = '' + @property({type: Number}) innerWidth = 0 + @property({type: Number}) distance = 0 + @property({type: Number}) currentDistance = 0 + @property({type: Number}) barWidth = 0 + @property({type: Number}) max = 100 + @property({type: Number}) value = 1 + @property() touchAction = { + // 触摸开始落点 + start: { + offsetX: 0, + offsetY: 0, + clientX: 0, + clientY: 0, + }, + + // 触摸结束落点 + last: { + offsetX: 0, + offsetY: 0, + clientX: 0, + clientY: 0, + }, + } + + @property({type: String}) + get coverLen() { + return this._coverLen + } + + set coverLen(value: string) { + this.style.setProperty('--cover-length', value) + this._coverLen = value + } + + render(): HTMLTemplateResult { + return html` +
+
+
+ ` + } + + static styles = css` + :host { + width: inherit; + height: inherit; + dislay: block; + --cover-length: 3.78px; // 亮度为1 + --background-lm: rgba(255, 255, 255, 0.5); + --background-dm: rgba(0, 0, 0, 0.15); + --progress-background-lm: rgba(255, 255, 255, 0.8); + --progress-background-dm: rgba(255, 255, 255, 0.7); + } + + .sliderBar { + width: inherit; + height: inherit; + position: absolute; + left: 0px; + right: 0px; + background: var(--background-lm); + } + + .progress { + width: var(--cover-length); + height: 100%; + position: absolute; + left: 0px; + right: 0px; + background: var(--progress-background-lm); + } + + .sliderBar::before { + position: absolute; + content: attr(data-icon); + font-family: gaia-icons; + font-style: normal; + text-rendering: optimizelegibility; + font-weight: 500; + } + + @media screen and (max-width: 1200px) { + .sliderBar { + border-radius: 16px; + } + + .progress { + border-radius: 16px; + } + + .sliderBar::before { + width: 48px; + height: 48px; + left: 29px; + top: 29px; + font-size: 48px; + } + } + + @media screen and (max-width: 600px) { + .sliderBar { + border-radius: 8px; + } + + .progress { + border-radius: 8px; + } + + .sliderBar::before { + width: 24px; + height: 24px; + left: 14px; + top: 24px; + font-size: 24px; + } + + } + ` + + firstUpdated() { + if (this.value) { + let len = Math.floor((this.value * this.sliderBar.offsetWidth) / this.max) + this.coverLen = len.toString() + } + } + + handleEvent(event: TouchEvent) { + switch (event.type) { + case 'touchstart': + this.touchAction.start.clientX = event.touches[0].clientX + this.barWidth = this.sliderBar.offsetWidth + break + case 'touchmove': + this.touchAction.last.clientX = event.touches[0].clientX + this.distance = + this.touchAction.last.clientX - this.touchAction.start.clientX + this.currentDistance = this.distance + this.progress.offsetWidth + + if (this.currentDistance < 0) { + // this.currentDistance = 0; + this.currentDistance = this.barWidth / this.max + } + + if (this.currentDistance > this.barWidth) { + this.currentDistance = this.barWidth + } + this.progress.style.setProperty('width', this.currentDistance + 'px') + break + case 'touchend': + this.value = Math.floor( + (this.currentDistance * this.max) / this.barWidth + ) + this.dispatchEvent( + new CustomEvent('brightness-slider-change', { + detail: { + value: this.value, + }, + bubbles: true, + composed: true, + }) + ) + break + } + } + + setValue(value: number) { + this.value = value + let len = Math.floor((value * this.sliderBar.offsetWidth) / this.max) + this.coverLen = len.toString() + } +} + +declare global { + interface HTMLElementTagNameMap { + 'brightness-slider': BrightnessSlider + } +} diff --git a/src/components/brightness-slider/index.ts b/src/components/brightness-slider/index.ts new file mode 100644 index 0000000..3e3525d --- /dev/null +++ b/src/components/brightness-slider/index.ts @@ -0,0 +1 @@ +export * from './brightness-slider.js' diff --git a/src/components/brightness-slider/package.json b/src/components/brightness-slider/package.json new file mode 100644 index 0000000..1b62277 --- /dev/null +++ b/src/components/brightness-slider/package.json @@ -0,0 +1,22 @@ +{ + "name": "@star-web-components/brightness-slider", + "version": "0.0.1", + "description": "", + "type": "module", + "main": "./index.js", + "module": "./index.js", + "exports": { + ".": { + "default": "./index.js" + }, + "./index": { + "default": "./index.js" + }, + "./brightness-slider.js": { + "default": "./brightness-slider.js" + }, + "./package.json": "./package.json" + }, + "author": "", + "license": "ISC" +} diff --git a/src/components/control-center/tsconfig.json b/src/components/brightness-slider/tsconfig.json similarity index 71% rename from src/components/control-center/tsconfig.json rename to src/components/brightness-slider/tsconfig.json index d1d7546..4ba3e2c 100644 --- a/src/components/control-center/tsconfig.json +++ b/src/components/brightness-slider/tsconfig.json @@ -4,5 +4,5 @@ "composite": true, "rootDir": "../../" }, - "include": ["../../../global.d.ts", "*.ts"] -} \ No newline at end of file + "include": ["*.ts"] +} diff --git a/src/components/control-center/README.md b/src/components/control-center/README.md deleted file mode 100644 index 2c59bb4..0000000 --- a/src/components/control-center/README.md +++ /dev/null @@ -1,93 +0,0 @@ -# icon-item -用于显示下拉控件栏中的icon。 -分为两类: -`IconType.BASE`类型: -须传入`icon`(用于图标内容),`bgchange`(用于点击图标时的样式变化),`bgchange`未传参时,默认图标点击时不改变图标背景 -`IconType.WITH_STATE`类型: -须传入`icon`(用于图标内容),`stateDesc`(用于蓝牙、wifi状态显示) -可选参数`settingsKey`: 用于settingsObsever。 - -`IconType.BASE_WITHOUT_BORDER`类型: -须传入`icon`(用于图标内容),图标不带边框。 - - -示例: -```html - - - - - - - -``` - - -# icons-online -对`icon-item`的进一步组合、封装。 -分为两类: -`IconsOneLineType.BASE`类型: -需传入`count`,为所插入插槽元素的个数,默认数值为4; -需插入插槽元素,显示为一个box框,框内是由短竖线分隔开的基本图标。 -`IconsOneLineType.WITH_STATE`类型: -需传入`count`,为所插入插槽元素的个数,默认数值为2; -需插入插槽元素,显示为一行带状态的图标。 - -示例: -```html - - - - - - - - - - - - -``` - - -# header-bar -用于显示下拉控件栏、下拉通知栏最顶部的header。 -分为两类: -`HeaderBarType.ONLY_TIME`类型: -header中显示时间和任意图标,需插入插槽元素 -`HeaderBarType.DATE_TIME`类型: -header中显示日期、星期、时间和任意图标,需插入插槽元素 -示例: -```html - - - - - - - - - - -``` - -# control-center -下拉控件栏组件。 -包括`header-bar`和中间控件部分。中间控件部分由slot元素插入。 - -```html - -
- -
-``` - -# control-center-bar -`control-center`实例 - -说明: 因现有下拉栏顶部的状态栏是采用`background-image:-moz-element(#statusbar-icons)`方式获取,所以使用`slot`获取。 -```html - -
-
-``` \ No newline at end of file diff --git a/src/components/control-center/control-center-bar.ts b/src/components/control-center/control-center-bar.ts deleted file mode 100644 index 268ed4d..0000000 --- a/src/components/control-center/control-center-bar.ts +++ /dev/null @@ -1,926 +0,0 @@ -import { html, css, LitElement, HTMLTemplateResult } from 'lit' -import { customElement, property, query } from 'lit/decorators.js' -import { settingsObserver as settingsObserver} from "./mock_settings_observer"; -import { IconsOneLine, IconsOneLineType } from './icons-one-line' -import { IconItem, IconType } from './icon-item'; -import { PullDownMenuType } from './pull-down-menu'; -import './icons-one-line'; -import './icon-item'; -import './pull-down-menu'; -import './light-slider'; -import "./gaia-container"; -// import "../gaia_dialog/gaia-dialog-list.js"; -// import WifiContext from "../../js/utils/origin/wifi/wifi_context.js"; -import IconDB from "./icondb"; -import { LightSlider } from './light-slider'; -// import WifiNetworkList from "../../js/utils/origin/wifi/wifi_network_list.js"; -// import WifiItem from "../../js/utils/origin/wifi/wifi_item.js"; -// import BtTemplateFactory from '../../js/utils/origin/bluetooth/bt_template_factory.js'; -// import ListView from '../../js/utils/origin/mvvm/list_view.js'; -// import BtContext from '../../js/utils/origin/bluetooth/bluetooth_context.js'; -// import BluetoothItem from "../../js/utils/origin/bluetooth/bluetooth_item.js"; -const WIFIENABLED = "wifi.enabled"; -// const BLUETOOTHENABLED = "bluetooth.enabled"; -// const BRIGHTNESS = "screen.brightness"; -// const AUTOBRIGHTNESS = "screen.automatic-brightness"; -const GEOLOCATIONENABLED = "geolocation.enabled"; -const WIFI_HOTSPOT = "tethering.wifi.enabled"; -const LOCK_SCREEN_KEY = "screen.orientation.lock"; -// const AUDIO_VOLUME_NOTIFICATION = "audio.volume.notification"; -// const VIBRATEENABLED = "vibration.enabled"; -// const WIFI_SSID_KEY = "tethering.wifi.ssid"; -// const WIFI_SECURITY_KEY = "tethering.wifi.security.type"; -// const WIFI_PASSWORD_KEY = "tethering.wifi.security.password"; - -let _debug = false; -_debug = true; -let debug = function (msg?: string | any) { - console.log(msg); - }; -if (_debug) { - debug = function btp_debug(msg) { - console.log('--> [ControlCenter]: ' + msg); - }; -} - -@customElement('control-center-bar') -export class ControlCenterBar extends LitElement { - @query('gaia-container') icons!: any; - @query('gaia-dialog-list#wifi-list') wifiListDialog!: any; - @query('gaia-dialog-list#bluetooth-list') bluetoothListDialog!: any; - @query('icons-one-line[type="base"]') cameraPhoto!: IconsOneLine; - @query('icon-item[icon="bluetooth"]') bluetooth!: IconItem; - @query('icon-item[icon="wifi-4"]') wifi!: IconItem; - @query('icon-item[icon="brightness"]') autoBrightness!: IconItem; - @query('#screen-brightness') brightness!: LightSlider; - @property({type: IconDB}) icondb = new IconDB(); - @property() settings = { - wifi: false, - airplaneMode: false, - data: false, - bluetooth: false, - wifihotspot: false, - geolocation: false, - screenLock: false, - brightness: 1, - autoBrightness: false, - }; - @property({type: Number}) iconsLeft = 0; - @property({type: Number}) iconsRight = 0; - @property({type: Boolean}) airplaneModeSwitching = false; - @property({type: Number}) lastWindowWidth = window.innerWidth; - @property({type: Number}) lastWindowHeight = window.innerHeight; - @property() pairedDevicesListView = null; - @property({type: String}) iconOnlyElements = ["data", "airplane-mode", "geolocation", "wifi-hotspot", "dark-mode", "sound", "auto-rotate", "addons"]; - @property({type: []}) startupOrder !: any[]; - @property({type: Boolean}) draggable = false; - @property({type: Number}) minRange = 10; // 最小滑动距离 - @property() touchAction = { // 触摸开始落点 - start: { - pageX: 0, - pageY: 0, - clientX: 0, - clientY: 0 - }, - - last: { // 触摸结束落点 - pageX: 0, - pageY: 0, - clientX: 0, - clientY: 0 - } - } - @property({type: Number}) preVolumeValue = 1; - @property({type: IconItem}) wifiHotspot!: IconItem; - @property({type: IconItem}) autoRotate!: IconItem; - @property({type: IconItem}) sound!: IconItem; - @property({type: IconItem}) airplaneMode!: IconItem; - @property({type: IconItem}) data!: IconItem; - @property({type: IconItem}) geolocation!: IconItem; - @property({type: Number}) timer!: NodeJS.Timeout; - render(): HTMLTemplateResult { - console.log("dddd render"); - return html` - - - - - - -
- -
-
- - -
- - - - - - -
-
-
-
- - -
- ` - } - - static styles = css` - :host { - --background-color-lm: rgba(217, 217, 217, 0.65); - --background-color-dm: rgba(89, 89, 89, 0.68); - width: inherit; - height: inherit; - display: block; - background: var(--background-color-lm); - backdrop-filter: blur(120px); - transform: translateY(0); - transition: transform 300ms ease, visibility 300ms; - visibility: hidden; - } - - :host([open]) { - visibility: visible; - } - - ::slotted(div) { - background-image: -moz-element(#statusbar-icons); - background-repeat: no-repeat; - width: 100%; - height: 3rem; - filter: none; - // background-position: 600px center; - background-position: right; - } - - pull-down-menu { - // width: 100%; - // height: calc(100% - 3rem) - position; absolute; - top: 140px; - left: 628px; - width: 512px; - } - - icons-one-line { - width: 512px; - height: 112px; - } - - icons-one-line[type='with-state'] { - position: relative; - top: 40px; - } - - .icon-section { - // width: inherit; - // height: 238px; - - width: 540px; - height: 268px; - position: relative; - top: 72px; - - left: -9px; - } - - gaia-container { - width: 100%; - height: 100%; - display: flex; - flex-flow: row wrap; - align-content: flex-start; - box-sizing: padding-box; - } - - .icon-container { - // height: 119px; - // width: 128px; - height: 134px; - width: 135px; - position: relative; - display: inline-block; - } - - .icon-container > icon-item { - position: absolute; - top: 0; - left: 0; - transition: transform 0.2s, opacity 0.2s; - transform: translate(12px, 7.5px); - } - - gaia-container:not(.loading) > .gaia-container-child:not(.added):not(.dragging) { - transition: transform 0.2s; - } - - gaia-container > .gaia-container-child.dragging { - z-index: 1; - will-change: transform; - } - - .brightness { - display: flex; - align-items: center; - justify-content: space-between; - - position: relative; - // top: 104px; - top: 89px; //104-15 - } - - #screen-brightness { - width: 378px; - height: 104px; - } - - icons-one-line[type='base'] { - position: relative; - top: 136px; - } - - #toggle-button { - width: 88px; - height: 10px; - - background: rgba(255, 255, 255, 0.35); - border-radius: 16px; - } - - .media-player { // 占位隐藏 - // width: inherit; - // height: 134px; - // position: relative; - // top: 200px; - // border: 1px solid white; - - // height: 67px; - // top: 100px; - // border: 0.5px solid white; - } - - .button-wrapper { - position: relative; - top: 168px; - display: flex; - justify-content: center; - } - - :host([dark-mode]) { - width: inherit; - height: inherit; - display: block; - background: var(--background-color-dm); - backdrop-filter: blur(120px); - } - - [disabled="true"] { - pointer-events: none; - opacity: 0.2; - } - ` - - firstUpdated() { - this.iconAdded().then(() => { - this.monitorWifiChange(); - this.monitorTetheringStatusChange(); - window.addEventListener("send-to-control-center", this.toggleActive.bind(this)); - this.monitorAirplaneModeChange(); - this.monitorBluetoothChange(); - - this.cameraPhoto.addEventListener("click", this.handleCamera.bind(this)); - // ["click", "touchstart", "touchend", "drag-end", - ["touch-start", "touchend", "drag-end", - "drag-rearrange", "drag-finish"].forEach(eventName => { - this.icons.addEventListener(eventName, this.handleContainerEvent.bind(this)) - }); - - - [this.wifiListDialog, this.bluetoothListDialog].forEach(dialog => { - dialog.addEventListener("more-settings", this.handleNavigate.bind(this)); - }); - - window.addEventListener("touchstart", this.handleStart.bind(this)); - window.addEventListener("touchmove", this.handleMove.bind(this)); - window.addEventListener("editor-action", this.handleEditor.bind(this)); - window.addEventListener("icon-item-click", this.handleIconButtonClick.bind(this)); - window.addEventListener("more-info-action", this.showListDialog.bind(this)); - }); - - } - - iconAdded() { - return new Promise((resolve: (value: void) => void) => { - this.icondb.init().then(() => { - // return this.icondb.getAll((result: any) => { - // console.log("iconAdded icondb getAll: ", result); - - // if (result) { - // let id = result.id; - // this.startupOrder.push(id); - // this.iconOnlyElements = this.startupOrder; - // } - // return Promise.resolve(); - // }); - }).then(() => { - this.addIcon(); - resolve(); - }); - }); - } - - toggleActive() { - if (this.autoBrightness.active == this.settings.autoBrightness) { - this.autoBrightness.activeOrInactive(!this.settings.autoBrightness); - } - if (this.geolocation.active == this.settings.geolocation) { - this.geolocation.activeOrInactive(!this.settings.geolocation); - } - - if (this.wifiHotspot.active == this.settings.wifihotspot) { - this.wifiHotspot.activeOrInactive(!this.settings.wifihotspot); - } - - if (this.autoRotate.active == this.settings.screenLock) { - - this.autoRotate.activeOrInactive(!this.settings.screenLock); - } - - if (this.brightness.value == this.settings.brightness) { - - // this.brightness.value = this.settings.brightness; - this.brightness.setValue(this.settings.brightness); - } - } - - - monitorWifiChange() { - // WifiItem(this.wifiStatusText).enabled = true; - // WifiItem(this.wifi.stateDesc).enabled = true; - window.addEventListener("wifi-enabled", this.handleWifiChange.bind(this)); - window.addEventListener("wifi-disabled", this.handleWifiChange.bind(this)); - window.addEventListener("wifi-statuschange", this.handleWifiChange.bind(this)); - } - - monitorAirplaneModeChange() { - - window.addEventListener("send-airplaneMode-status", (evt: any) => { - let value = evt.detail.value; - this.airplaneModeSwitching = false; - let target = this.airplaneMode; // 飞行模式element - - switch (value) { - case "enabled": - this.setSettingEnabled("airplaneMode", true); - target.activeOrInactive(false); // addClass - this.wifiHotspot.setAttribute("disabled", "true"); // 飞行模式下禁用wifi热点和移动数据 - this.data.setAttribute("disabled", "true"); - if (this.data.active) { - this.data.activeOrInactive(true); - } - break; - case "disabled": - this.setSettingEnabled("airplaneMode", false); - target.activeOrInactive(true);// removeClass - this.wifiHotspot.removeAttribute("disabled"); - this.data.removeAttribute("disabled"); - if (!this.data.active) { - this.data.activeOrInactive(false); - } - break; - case "enabling": - this.airplaneModeSwitching = true; - break; - case "disabling": - this.airplaneModeSwitching = true; - break; - } - }); - } - - monitorBluetoothChange() { - window.addEventListener("bluetooth-enabled", this.handleBlueToothChange.bind(this)); - window.addEventListener("bluetooth-disabled", this.handleBlueToothChange.bind(this)); - } - - monitorTetheringStatusChange() { - window.addEventListener("tethering-status-change", evt => { - settingsObserver.getValue(WIFIENABLED).then(wifiEnabled => { - if (!wifiEnabled && (evt as any).detail === 0) { // wifi打开状态下,wifi热点打开再关闭, 应恢复wifi - settingsObserver.setValue([{name: WIFIENABLED, value: true }]); - } - }); - }); - } - - setSettingEnabled(settingKey: string, enabled: any) { - (this.settings as any)[settingKey] = enabled; - } - - onPairedDeviceItemClick(deviceItem: any) { - debug('onPairedDeviceItemClick(): deviceItem.address = ' + - deviceItem.address); - debug('onPairedDeviceItemClick(): deviceItem.paired = ' + - deviceItem.paired); - } - - handleWifiChange(evt: Event) { - evt.preventDefault(); - switch (evt.type) { - case "wifi-enabled": - // debug("handleWifiChange wifi-enabled!!"); - this.setSettingEnabled("wifi", true); - this.wifi.activeOrInactive(false); - this.scan(); - break; - case "wifi-disabled": - // debug("handleWifiChange wifi-disabled!!"); - this.setSettingEnabled("wifi", false); - this.wifi.activeOrInactive(true); - /* - WifiItem(this.wifi.stateDesc).enabled = false; - */ - break; - case "wifi-statuschange": - // debug("handleWifiChange wifi-statuschange!!"); - let scanStates = new Set(["connected", "connectingfailed", "disconnected"]); - if (scanStates.has((evt as any).detail.event.status)) { - this.scan(); - } - break; - } - } - - handleBlueToothChange(event: Event) { - // event.preventDefault(); - switch (event.type) { - case "bluetooth-enabled": - this.setSettingEnabled("bluetooth", true); - this.bluetooth.activeOrInactive(false); - - // let pairedDeviceTemplate = - // BtTemplateFactory("paired", this.onPairedDeviceItemClick.bind(this)); - - // this.pairedDevicesListView = ListView(this.bluetoothListDialog, - // BtContext.getPairedDevices(), - // pairedDeviceTemplate); - (this.pairedDevicesListView as any).enabled = true; - break; - case "bluetooth-disabled": - this.setSettingEnabled("bluetooth", false); - this.bluetooth.activeOrInactive(true); - if (this.pairedDevicesListView) { - (this.pairedDevicesListView as any).enabled = false; - } - break; - } - } - - handleEditor() { - let dragAndDrop = this.icons.getAttribute("drag-and-drop"); - this.icons.setAttribute("drag-and-drop", (!dragAndDrop).toString()); - this.draggable = !dragAndDrop; - } - - handleSettings() { - let activity = new WebActivity("configure", {}); - activity.start().then(() => {}, () => {}); - } - - showListDialog(event: Event) { - let target = (event as any).detail; - switch (target) { - case "wifi-4": - this.wifiListDialog.open(event); - break; - case "bluetooth": - this.bluetoothListDialog.open(event); - break; - } - } - - handleIconButtonClick(event: any) { - let target = event.detail.target; - console.log("handleIconButtonClick target: ", target); - console.log("handleIconButtonClick event.detail: ", event.detail); - let isContainer = target.parentElement?.parentElement?.parentElement?.id == "icon-only"; - if (isContainer && this.draggable) { - return; - } - - let isActive = event.detail.isActive; - let id = event.detail.id; - - switch (id) { - case "wifi": - if (this.airplaneModeSwitching) { - return; - } - this.fireEvent(id, !isActive); - break; - case "bluetooth": - if (this.airplaneModeSwitching) { - return; - } - let enabled = this.settings.bluetooth; - var toggleb = enabled ? - "request-disable-bluetooth" : - "request-enable-bluetooth"; - this.dispatchEvent( - new CustomEvent(toggleb, { - bubbles: true, - composed: true, - }) - ); - break; - case "screen-auto-brightness": - this.fireEvent(id, !isActive); - break; - case "airplane-mode": - if (this.airplaneModeSwitching) { - return; - } - - var toggle = isActive ? - "request-airplane-mode-disable" : - "request-airplane-mode-enable"; - this.dispatchEvent( - new CustomEvent(toggle, { - bubbles: true, - composed: true, - }) - ); - if (isActive) { - this.wifiHotspot.removeAttribute("disabled"); - this.data.removeAttribute("disabled"); - } else { - this.wifiHotspot.setAttribute("disabled", "true"); - this.data.setAttribute("disabled", "true"); - } - break; - case "geolocation": - this.fireEvent(id, !isActive); - break; - case "wifi-hotspot": - if (this.airplaneModeSwitching) { - return; - } - this.fireEvent(id, !isActive); - break; - case "dark-mode": - break; - - case "sound": - if (this.sound.icon == "alarm") { - this.sound.icon = "mute"; - this.fireEvent("mute", 0); - } else if (this.sound.icon == "mute") { - this.sound.icon = "alarm"; - this.fireEvent("alarm", this.preVolumeValue); - } - break; - - case "auto-rotate": - this.fireEvent(id, !isActive); - break; - } - } - - handleIconButtonPress(event: any) { - let target = event.detail.target; - let isContainer = target.parentElement?.parentElement?.parentElement?.id == "icon-only"; - - if (isContainer && this.draggable) { - return; - } - - if (target.className == "icon-container") { - target = target.children[0]; - } - - if (target.getAttribute("disabled") === "true") { - return; - } - - this.close(); - let section = target.id; - this.timer = setTimeout(() => { - let activity = new WebActivity("moz_configure_window", { - data: { - target: "device", - section: section - } - }); - activity.start(); - }, 800); - } - - handleIconButtonPressEnd(event: any) { - let target = event.target; - let isContainer = target.parentElement?.parentElement?.parentElement?.id == "icon-only"; - if (isContainer && this.draggable) { - return; - } - clearTimeout(this.timer); - } - - handleNavigate(event: any) { - let section = event.target.id; - let activity = new WebActivity("moz_configure_window", { - data: { - target: "device", - section: section - } - }); - activity.start(); - } - - handleCamera(event: any) { - let target = event.target.icon; - switch (target) { - case "crop": - this.dispatchEvent( - new CustomEvent("volumedown+sleep", { - bubbles: true, - composed: true, - }) - ); - this.close(); - break; - case "video": - let takeVideo = new WebActivity("record", { - type: "videos" - }); - takeVideo.start(); - this.close(); - break; - case "camera": - let takePhotos = new WebActivity("record", { - type: "photos" - }); - takePhotos.start(); - this.close(); - break; - case "shut-down": - // powerManager.powerOff(); - break; - } - } - - handleContainerEvent(event: Event) { - switch (event.type) { - case "icon-item-click": - this.handleIconButtonClick(event); - break; - case "touch-start": - this.handleIconButtonPress(event); - break; - case "touchend": - this.handleIconButtonPressEnd(event); - break; - case "drag-end": - case "drag-rearrange": - case "drag-finish": - this.handleContainerDrag(event); - break; - } - } - - handleContainerDrag(e: any) { - switch(e.type) { - // Activate drag-and-drop immediately for selected icons - case "touchstart": - this.icons.dragAndDropTimeout = 0; - break; - - case "drag-finish": - debug("Drag-finish"); - // Restore normal drag-and-drop after dragging selected icons - this.icons.dragAndDropTimeout = -1; - break; - - // Handle icon editing and dragging to the end of the icon grid. - case "drag-end": - debug("Drag-end, target: " + (e.detail.dropTarget ? - e.detail.dropTarget.firstElementChild : "none"));//e.detail.target --> div.icon-container - - if (e.detail.dropTarget === null && - e.detail.clientX >= this.iconsLeft && - e.detail.clientX < this.iconsRight) { - // If the drop target is null, and the client coordinates are - // within the panel, we must be dropping over the start or end of - // the container. - e.preventDefault(); - let bottom = e.detail.clientY < this.lastWindowHeight / 2; - debug("Reordering dragged icon to " + - (bottom ? "bottom" : "top")); - this.icons.reorderChild(e.detail.target, - bottom ? this.icons.firstChild : null as any, - this.storeIconOrder.bind(this)); - break; - } - break; - - // Save the icon grid after rearrangement - case "drag-rearrange": - debug("Drag rearrange"); - this.storeIconOrder(); - break; - } - } - - scan() { - // WifiNetworkList(this.wifiListDialog).scan(); - } - - clearList(enabled: boolean) { - console.log(enabled); - - // WifiNetworkList(this.wifiListDialog).clear(enabled); - } - - activeOrInactive(isActive: boolean, element: HTMLElement) { - if (element.id === "sound") { - element.classList.add("active"); - return; - } - isActive ? element.classList.remove("active") : - element.classList.add("active"); - } - - addIcon() { - this.iconOnlyElements.forEach((icon) => { - let iconDiv = document.createElement("icon-item"); - iconDiv.type = "base"; - iconDiv.id = icon; - let key = null; - switch (icon) { - case "data": - iconDiv.icon = "data"; - iconDiv.bgchange = true; - break; - case "airplane-mode": - iconDiv.icon = "airplane"; - iconDiv.bgchange = true; - break; - case "geolocation": - key = GEOLOCATIONENABLED; - iconDiv.icon = "location"; - iconDiv.bgchange = true; - break; - case "wifi-hotspot": - key = WIFI_HOTSPOT; - iconDiv.icon = "tethering"; - iconDiv.bgchange = true; - break; - case "dark-mode": - iconDiv.icon = "themes"; - iconDiv.bgchange = true; - break; - case "auto-rotate": - key = LOCK_SCREEN_KEY; - iconDiv.icon = "sync"; - iconDiv.bgchange = true; - break; - case "sound": - iconDiv.icon = "alarm"; - iconDiv.id = "sound"; - iconDiv.bgchange = true; - break; - // 填充 无意义 - case "addons": - iconDiv.icon = "addons"; - iconDiv.id = "addons"; - iconDiv.bgchange = true; - break; - } - - if (key) { - iconDiv.settingsKey = key; - } - - // iconDiv.id = icon; - // iconDiv.setAttribute("id", icon); - (this as any)[this.toCamelCase(iconDiv.id)] = iconDiv; - this.addIconContainer(iconDiv); - }); - } - - addIconContainer(iconDiv: IconItem) { - let container = document.createElement("div") as HTMLElement; - container.classList.add("icon-container"); - (container as any).order = -1; - container.appendChild(iconDiv); - - if (!container.parentNode) { - this.icons.appendChild(container); - this.refreshGridSize(); - } - } - - refreshGridSize() { - let children = this.icons.children; - let visibleChildren = 0; - let cols = 4; - let firstVisibleChild = -1; - for (let i = 0, iLen = children.length; i < iLen; i++) { - // if ((children[i] as HTMLElement).style.display !== "none") { - visibleChildren ++; - if (firstVisibleChild === -1) { - firstVisibleChild = i; - this.iconsLeft = this.icons.getChildOffsetRect((children[i]) as HTMLElement).left; - } else if (visibleChildren === cols) { - this.iconsRight = this.icons.getChildOffsetRect(children[i] as HTMLElement).right; - } - // } - } - } - - toCamelCase(str: string) { - return str.replace(/\-(.)/g, function replacer(str, p1) { - console.log(str); - return p1.toUpperCase(); - }); - } - - storeIconOrder() { - let storedOrders = []; - let children = this.icons.children; - for (let i = 0, iLen = children.length; i < iLen; i++) { - let icon = children[i].firstElementChild as Element; - storedOrders.push({ id: icon.id, order: i }); - } - this.icondb.set(storedOrders).then( - () => {}, - (e) => { - console.error("Error storing icon order", e); - }); - } - - handleStart(event: TouchEvent) { - this.touchAction.start.pageX = event.touches[0].pageX; - this.touchAction.start.pageY = event.touches[0].pageY; - } - - handleMove(event: TouchEvent) { - this.touchAction.last.pageX = event.touches[0].pageX; - this.touchAction.last.pageY = event.touches[0].pageY; - let distanceY = this.touchAction.last.pageY - this.touchAction.start.pageY; - - if (this.touchAction.start.pageY > 0 && - this.touchAction.start.pageY < this.minRange && - this.touchAction.start.pageX > window.screen.width / 2 - && distanceY >= this.minRange) { - this.open(); - } - - if (this.touchAction.start.pageY > window.screen.height - this.minRange - && this.touchAction.start.pageY <= window.screen.height) { - this.close(); - } - } - - open() { - let isOpen = this.getAttribute("open"); - if (isOpen !== "") { - this.setAttribute("open", ""); - } - } - - close() { - let isOpen = this.getAttribute("open"); - if (isOpen == "") { - this.removeAttribute("open"); - } - } - - fireEvent(name: string, value: string | boolean | number) { - this.dispatchEvent( - new CustomEvent("control-center-dispatched", { - detail: { - name, - value - }, - bubbles: true, - composed: true, - }) - ) - } -} - -declare global { - interface HTMLElementTagNameMap { - 'control-center-bar': ControlCenterBar - } -} \ No newline at end of file diff --git a/src/components/control-center/gaia-container-child.js b/src/components/control-center/gaia-container-child.js deleted file mode 100644 index 2e94f9e..0000000 --- a/src/components/control-center/gaia-container-child.js +++ /dev/null @@ -1,103 +0,0 @@ - -export default class GaiaContainerChild { - constructor(element) { - this._element = element; - this.markDirty(); - } - - get element() { - return this._element; - } - - /** - * The element that will contain the child element and control its position. - */ - get container() { - if (!this._container) { - // Create container - let container = document.createElement("div"); - container.classList.add("gaia-container-child"); - container.style.position = "absolute"; - container.style.top = "0"; - container.style.left = "0"; - container.appendChild(this.element);//this.element是div.icon-container - - this._container = container; - } - return this._container; - } - - /** - * The element that will be added to the container that will - * control the element's transform. - */ - get master() { - if (!this._master) { - // Create master - let master = document.createElement("div"); - master.style.visibility = "hidden"; - this._master = master; - - } - return this._master; - } - - /** - * Clears any cached style properties. To be used if elements are - * manipulated outside of the methods of this object. - */ - markDirty() { - this._lastElementWidth = null; - this._lastElementHeight = null; - this._lastElementDisplay = null; - this._lastElementOrder = null; - this._lastMasterTop = null; - this._lastMasterLeft = null; - } - - /** - * Synchronise the size of the master with the managed child element. - */ - synchroniseMaster() { - let master = this.master; - let element = this.element; - - let style = window.getComputedStyle(element); - let display = style.display; - let order = style.order; - let width = element.offsetWidth; - let height = element.offsetHeight; - - if (this._lastElementWidth !== width || - this._lastElementHeight !== height || - this._lastElementDisplay !== display || - this._lastElementOrder !== order) { - this._lastElementWidth = width; - this._lastElementHeight = height; - this._lastElementDisplay = display; - this._lastElementOrder = order; - - master.style.width = width + "px"; - master.style.height = height + "px"; - master.style.display = display; - master.style.order = order; - } - } - - /** - * Synchronise the container's transform with the position of the master. - */ - synchroniseContainer() { - let master = this.master; - let container = this.container; - let top = master.offsetTop; - let left = master.offsetLeft; - - if (this._lastMasterTop !== top || - this._lastMasterLeft !== left) { - this._lastMasterTop = top; - this._lastMasterLeft = left; - container.style.transform = "translate(" + left + "px, " + top + "px)"; - } - } -} \ No newline at end of file diff --git a/src/components/control-center/gaia-container.js b/src/components/control-center/gaia-container.js deleted file mode 100644 index c1f1623..0000000 --- a/src/components/control-center/gaia-container.js +++ /dev/null @@ -1,789 +0,0 @@ -import GaiaContainerChild from "./gaia-container-child.js"; - -/** - * The time, in ms, to wait for an animation to start in response to a state - * change, before removing the associated style class. - */ -const STATE_CHANGE_TIMEOUT = 100; - -/** - * The time, in ms, to wait before initiating a drag-and-drop from a - * long-press. - */ -const DEFAULT_DND_TIMEOUT = 300; - -/** - * The distance, in CSS pixels, in which a touch or mouse point can deviate - * before it being discarded for initiation of a drag-and-drop action. - */ -const DND_THRESHOLD = 5; - -/** - * The minimum time between sending move events during drag-and-drop. - */ -const DND_MOVE_THROTTLE = 50; - -class GaiaContainer extends HTMLElement { - constructor() { - super(); - this.attachShadow({ mode: "open" }); - this.shadowRoot.innerHTML = this.template; - } - - connectedCallback() { - this._frozen = false; - this._pendingStateChanges = []; - this._children = []; - this._dnd = { - // Whether drag-and-drop is enabled - enabled: false, - - // The time, in ms, to wait before initiating a drag-and-drop from a - // long-press - delay: DEFAULT_DND_TIMEOUT, - - // Timeout used to initiate drag-and-drop actions - timeout: null, - - // The child that was tapped/clicked - child: null, - - // Whether a drag is active - active: false, - - // The start point of the drag action - start: { - pageX: 0, - pageY: 0, - clientX: 0, - clientY: 0 - }, - - // The last point of the drag action - last: { - pageX: 0, - pageY: 0, - clientX: 0, - clientY: 0, - timeStamp: 0 - }, - - // Timeout used to send drag-move events - moveTimeout: null, - - // The last time a move event was fired - lastMoveEventTime: 0, - - // Whether to capture the next click event - clickCapture: false, - }; - - let dndObserverCallback = (mutations) => { - if (this._dnd.enabled !== this.dragAndDrop) { - this._dnd.enabled = this.dragAndDrop; - if (this._dnd.enabled) { - this.addEventListener("touchstart", this); - this.addEventListener("touchmove", this); - this.addEventListener("touchcancel", this); - this.addEventListener("touchend", this); - this.addEventListener("mousedown", this); - this.addEventListener("mousemove", this); - this.addEventListener("mouseup", this); - this.addEventListener("click", this, true); - this.addEventListener("contextmenu", this, true); - } else { - this.cancelDrag(); - this.removeEventListener("touchstart", this); - this.removeEventListener("touchmove", this); - this.removeEventListener("touchcancel", this); - this.removeEventListener("touchend", this); - this.removeEventListener("mousedown", this); - this.removeEventListener("mousemove", this); - this.removeEventListener("mouseup", this); - this.removeEventListener("click", this, true); - this.removeEventListener("contextmenu", this, true); - } - } - }; - this.dndObserver = new MutationObserver(dndObserverCallback); - this.dndObserver.observe(this, { - attributes: true, - attributeFilter: ["drag-and-drop"] - }); - - dndObserverCallback(null); - } - - get children() { //div.icon-container - return this._children.map((child) => { - return child.element; - }); - } - - get firstChild() { - return this._children.length ? - this._children[0].element : - null; - } - - get lastChild() { - const length = this._children.length; - return (length ? - this._children[length - 1].element : - null); - } - - get dragAndDrop() { - return (this.getAttribute("drag-and-drop") !== null); - } - - get dragAndDropTimeout() { - return this._dnd.delay; - } - - set dragAndDropTimeout(timeout) { - if (timeout >= 0) { - this._dnd.delay = timeout; - } else { - this._dnd.delay = DEFAULT_DND_TIMEOUT; - } - } - - realAppendChild() { - let proto = HTMLElement.prototype.appendChild; - let func = proto.apply(this, arguments); - return func; - } - - realRemoveChild() { - let proto = HTMLElement.prototype.removeChild; - let func = proto.apply(this, arguments); - return func; - } - - realInsertBefore() { - let proto = HTMLElement.prototype.insertBefore; - let func = proto.apply(this, arguments); - return func; - } - - realReplaceChild() { - let proto = HTMLElement.prototype.replaceChild; - let func = proto.apply(this, arguments); - return func; - } - - appendChild(element, callback) { - this.insertBefore(element, null, callback); - } - - removeChild(element, callback) { - let children = this._children; - let childToRemove = null; - - for (let child of children) { - if (child.element === element) { - childToRemove = child; - break; - } - } - - if (childToRemove === null) { - throw "removeChild called on unknown child"; - } - let that = this; - this.changeState(childToRemove, "removed", () => { - that.realRemoveChild(childToRemove.container); - that.realRemoveChild(childToRemove.master); - - // Find the child again. We need to do this in case the container was - // manipulated between removing the child and this callback being reached. - for (let i = 0, iLen = children.length; i < iLen; i++) { - if (children[i] === childToRemove) { - children.splice(i, 1); - break; - } - } - - if (callback) { - callback(); - } - - this.synchronise(); - }); - } - - replaceChild(newElement, oldElement, callback) { - if (!newElement || !oldElement) { - throw "replaceChild called with null arguments"; - } - - // Unparent the newElement if necessary (with support for gaia-container) - if (newElement.parentNode) { - newElement.parentNode.removeChild(newElement, () => { - this.replaceChild(newElement, oldElement, callback); - }); - if (newElement.parentNode) { - return; - } - } - - // Remove the old child and add the new one, but don't run the removed/ - // added state changes. - let children = this._children; - - for (let i = 0, iLen = children.length; i < iLen; i++) { - let oldChild = children[i]; - if (oldChild.element === oldElement) { - let newChild = new GaiaContainerChild(newElement); - this.realInsertBefore(newChild.container, oldChild.container); - this.realInsertBefore(newChild.master, oldChild.master); - this.realRemoveChild(oldChild.container); - this.realRemoveChild(oldChild.master); - this.children.splice(i, 1, newChild); - this.synchronise(); - - if (callback) { - callback(); - } - return; - } - } - - throw "removeChild called on unknown child"; - } - - /** - * Reorders the given element to appear before referenceElement. - */ - reorderChild(element, referenceElement, callback) { - if (!element) { - throw "reorderChild called with null element"; - } - - let children = this._children; - let child = null; - let childIndex = null; - let referenceChild = null; - let referenceChildIndex = null; - - for (let i = 0, iLen = children.length; i < iLen; i++) { - if (children[i].element === element) { - child = children[i]; - childIndex = i; - } else if (children[i].element === referenceElement) { - referenceChild = children[i]; - referenceChildIndex = i; - } - - if (child && (referenceChild || !referenceElement)) { - this.realRemoveChild(child.container); - this.realRemoveChild(child.master); - children.splice(childIndex, 1); - - if (referenceChild) { - this.realInsertBefore(child.container, referenceChild.container); - this.realInsertBefore(child.master, referenceChild.master); - } else { - (children.length === 0) ? - this.realAppendChild(child.container): - this.realInsertBefore(child.container, children[0].master); - this.realAppendChild(child.master); - } - - referenceChild ? - children.splice( - referenceChildIndex - (childIndex < referenceChildIndex) ? 1 : 0, - 0, child) : - children.splice(children.length, 0, child); - - this.synchronise(); - - if (callback) { - callback(); - } - return; - } - } - - throw child ? "reorderChild called on unknown reference element" : - "reorderChild called on unknown child"; - } - - insertBefore(element, reference, callback) { - let children = this._children; - let childToInsert = new GaiaContainerChild(element); - // console.log("childToInsert: ",childToInsert);// gaia-container-child - // console.log("children: ", children);//包括gaia-container-child 、icon-container等 - let referenceIndex = -1; - - if (reference !== null) { - for (let i = 0, iLen = children.length; i < iLen; i++) { - if (children[i].element === reference) { - referenceIndex = i; - break; - } - } - if (referenceIndex === -1) { - throw "insertBefore called on unknown child"; - } - } - - if (referenceIndex === -1) { - (children.length === 0) ? - this.realAppendChild(childToInsert.container): - this.realInsertBefore(childToInsert.container, children[0].master); - this.realAppendChild(childToInsert.master); - children.push(childToInsert); - } else { - this.realInsertBefore(childToInsert.container, - children[referenceIndex].container); - this.realInsertBefore(childToInsert.master, - children[referenceIndex].master); - children.splice(referenceIndex, 0, childToInsert); - } - - this.changeState(childToInsert, "added", callback); - this.synchronise(); - } - - /** - * Used to execute a state-change of a child that may possibly be animated. - * @state will be added to the child's class-list. If an animation starts that - * has the same name, that animation will complete and @callback will be - * called. Otherwise, the class will be removed and @callback called on the - * next frame. - */ - changeState(child, state, callback) { - // Check that the child is still attached to this parent (can happen if - // the child is removed while frozen). - if (child.container.parentNode !== this) { - return; - } - - // Check for a redundant state change. - if (child.container.classList.contains(state)) { - return; - } - - // Queue up state change if we're frozen. - if (this._frozen) { - this._pendingStateChanges.push( - this.changeState.bind(this, child, state, callback)); - return; - } - - let animStart = (e) => { - if (!e.animationName.endsWith(state)) { - return; - } - - child.container.removeEventListener("animationstart", animStart); - - window.clearTimeout(child[state]); - delete child[state]; - - let self = this; - child.container.addEventListener("animationend", function animEnd() { - child.container.removeEventListener("animationend", animEnd); - child.container.classList.remove(state); - if (callback) { - callback(); - } - }); - }; - - child.container.addEventListener("animationstart", animStart); - child.container.classList.add(state); - - child[state] = window.setTimeout(() => { - delete child[state]; - child.container.removeEventListener("animationstart", animStart); - child.container.classList.remove(state); - if (callback) { - callback(); - } - }, STATE_CHANGE_TIMEOUT); - } - - getChildOffsetRect(element) { - let children = this._children; - for (let i = 0, iLen = children.length; i < iLen; i++) { - let child = children[i]; - if (child.element === element) { - let top = child._lastMasterTop; - let left = child._lastMasterLeft; - let width = child._lastElementWidth; - let height = child._lastElementHeight; - - return { - top: top, - left: left, - width: width, - height: height, - right: left + width, - bottom: top + height - }; - } - } - - throw "getChildOffsetRect called on unknown child"; - } - - getChildFromPoint(x, y) { - let children = this._children; - for (let parent = this.parentElement; parent; parent = parent.parentElement) { - x += parent.scrollLeft - parent.offsetLeft; - y += parent.scrollTop - parent.offsetTop; - } - for (let i = 0, iLen = children.length; i < iLen; i++) { - let child = children[i]; - if (x >= child._lastMasterLeft && - y >= child._lastMasterTop && - x < child._lastMasterLeft + child._lastElementWidth && - y < child._lastMasterTop + child._lastElementHeight) { - return child.element; - } - } - - return null; - } - - cancelDrag() { - if (this._dnd.timeout !== null) { - clearTimeout(this._dnd.timeout); - this._dnd.timeout = null; - } - - if (this._dnd.moveTimeout !== null) { - clearTimeout(this._dnd.moveTimeout); - this._dnd.moveTimeout = null; - } - - if (this._dnd.active) { - this._dnd.child.container.classList.remove("dragging"); - this._dnd.child.container.style.position = "absolute"; - this._dnd.child.container.style.top = "0"; - this._dnd.child.container.style.left = "0"; - this._dnd.child.markDirty(); - this._dnd.child = null; - this._dnd.active = false; - this.synchronise(); - this._dnd.clickCapture = true; - this.dispatchEvent(new CustomEvent("drag-finish")); - } - } - - startDrag() { - if (!this.dispatchEvent(new CustomEvent("drag-start", { - cancelable: true, - detail: { - target: this._dnd.child.element, - pageX: this._dnd.start.pageX, - pageY: this._dnd.start.pageY, - clientX: this._dnd.start.clientX, - clientY: this._dnd.start.clientY - } - }))) { - return; - } - - this._dnd.active = true; - this._dnd.child.container.classList.add("dragging"); - this._dnd.child.container.style.position = "fixed"; - let rect = this.getBoundingClientRect(); - this._dnd.child.container.style.top = rect.top + "px"; - this._dnd.child.container.style.left = rect.left + "px"; - } - - continueDrag() { - if (!this._dnd.active) { - return; - } - - let left = this._dnd.child.master.offsetLeft + - (this._dnd.last.pageX - this._dnd.start.pageX); - let top = this._dnd.child.master.offsetTop + - (this._dnd.last.pageY - this._dnd.start.pageY); - this._dnd.child.container.style.transform = - "translate(" + left + "px, " + top + "px)"; - - if (this._dnd.moveTimeout === null) { - let delay = Math.max(0, DND_MOVE_THROTTLE - - (this._dnd.last.timeStamp - this._dnd.lastMoveEventTime)); - this._dnd.moveTimeout = setTimeout(() => { - this._dnd.moveTimeout = null; - this._dnd.lastMoveEventTime = this._dnd.last.timeStamp; - this.dispatchEvent(new CustomEvent("drag-move", { - detail: { - target: this._dnd.child.element, - pageX: this._dnd.last.pageX, - pageY: this._dnd.last.pageY, - clientX: this._dnd.last.clientX, - clientY: this._dnd.last.clientY - } - })); - }, delay); - } - } - - endDrag(event) { - if (this._dnd.active) { - let dropTarget = this.getChildFromPoint(this._dnd.last.clientX, - this._dnd.last.clientY); - - if (this.dispatchEvent(new CustomEvent("drag-end", { - cancelable: true, - detail: { - target: this._dnd.child.element, - dropTarget: dropTarget, - pageX: this._dnd.last.pageX, - pageY: this._dnd.last.pageY, - clientX: this._dnd.last.clientX, - clientY: this._dnd.last.clientY - } - }))) { - let children = this._children; - - if (dropTarget && dropTarget !== this._dnd.child.element) { - let dropChild = null; - let dropIndex = -1; - let childIndex = -1; - let insertBefore = true; - for (let i = 0, iLen = children.length; i < iLen; i++) { - if (children[i] === this._dnd.child) { - childIndex = i; - if (!dropChild) { - insertBefore = false; - } - } - - if (children[i].element === dropTarget) { - dropChild = children[i]; - dropIndex = i; - } - - if (dropIndex >= 0 && childIndex >= 0) { - break; - } - } - - if (dropIndex >= 0 && childIndex >= 0) { - // Default action, rearrange the dragged child to before or after - // the child underneath the touch/mouse point. - this.realRemoveChild(this._dnd.child.container); - this.realRemoveChild(this._dnd.child.master); - this.realInsertBefore(this._dnd.child.container, - insertBefore ? dropChild.container : - dropChild.container.nextSibling); - this.realInsertBefore(this._dnd.child.master, - insertBefore ? dropChild.master : - dropChild.master.nextSibling); - children.splice(dropIndex, 0, - children.splice(childIndex, 1)[0]); - this.dispatchEvent(new CustomEvent("drag-rearrange")); - } - } - } - } else if (this._dnd.timeout !== null) { - let handled = !this.dispatchEvent(new CustomEvent("activate", { - cancelable: true, - detail: { - target: this._dnd.child.element - } - })); - if (handled) { - event.stopImmediatePropagation(); - event.preventDefault(); - } - } - - this.cancelDrag(); - } - - handleEvent(event) { - switch (event.type) { - case "touchstart": - case "mousedown": - if (this._dnd.active || this._dnd.timeout) { - this.cancelDrag(); - break; - } - - if (event instanceof MouseEvent) { - this._dnd.start.pageX = event.pageX; - this._dnd.start.pageY = event.pageY; - this._dnd.start.clientX = event.clientX; - this._dnd.start.clientY = event.clientY; - // this._dnd.start.clientX = event.pageX; - // this._dnd.start.clientY = event.pageY; - } else { - this._dnd.start.pageX = event.touches[0].pageX; - this._dnd.start.pageY = event.touches[0].pageY; - this._dnd.start.clientX = event.touches[0].clientX; - this._dnd.start.clientY = event.touches[0].clientY; - } - - this._dnd.last.pageX = this._dnd.start.pageX; - this._dnd.last.pageY = this._dnd.start.pageY; - this._dnd.last.clientX = this._dnd.start.clientX; - this._dnd.last.clientY = this._dnd.start.clientY; - this._dnd.last.timeStamp = event.timeStamp; - - let target = event.target;//gaia-app-icon - - for (; target.parentNode !== this; target = target.parentNode) { - if (target === this || !target.parentNode) { - return; - } - } - - // Find the child - let children = this._children; - for (let child of children) { - if (child.container === target) { - this._dnd.child = child; - break; - } - } - - if (!this._dnd.child) { - return; - } - - if (this._dnd.delay > 0) { - this._dnd.timeout = setTimeout(() => { - this._dnd.timeout = null; - this.startDrag(); - }, this._dnd.delay); - } else { - this.startDrag(); - } - break; - - case "touchmove": - case "mousemove": - let pageX, pageY, clientX, clientY; - if (event instanceof MouseEvent) { - pageX = event.pageX; - pageY = event.pageY; - clientX = event.clientX; - clientY = event.clientY; - } else { - pageX = event.touches[0].pageX; - pageY = event.touches[0].pageY; - clientX = event.touches[0].clientX; - clientY = event.touches[0].clientY; - } - - if (this._dnd.timeout) { - if (Math.abs(pageX - this._dnd.start.pageX) > DND_THRESHOLD || - Math.abs(pageY - this._dnd.start.pageY) > DND_THRESHOLD) { - clearTimeout(this._dnd.timeout); - this._dnd.timeout = null; - } - } else if (this._dnd.active) { - event.preventDefault(); - this._dnd.last.pageX = pageX; - this._dnd.last.pageY = pageY; - this._dnd.last.clientX = clientX; - this._dnd.last.clientY = clientY; - this._dnd.last.timeStamp = event.timeStamp; - - this.continueDrag(); - } - break; - - case "touchcancel": - this.cancelDrag(); - break; - - case "touchend": - case "mouseup": - if (this._dnd.active) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - this.endDrag(event); - break; - - case "click": - if (this._dnd.clickCapture) { - this._dnd.clickCapture = false; - event.preventDefault(); - event.stopImmediatePropagation(); - } - break; - - case "contextmenu": - if (this._dnd.active || this._dnd.timeout) { - event.stopImmediatePropagation(); - // event.preventDefault(); - } - break; - } - } - - /** - * Temporarily disables element position synchronisation. Useful when adding - * multiple elements to the container at the same time, or in quick - * succession. - */ - freeze() { - this._frozen = true; - } - - /** - * Enables element position synchronisation after freeze() has been called. - */ - thaw() { - if (this._frozen) { - this._frozen = false; - for (let callback of this._pendingStateChanges) { - callback(); - } - this._pendingStateChanges = []; - this.synchronise(); - } - } - - /** - * Synchronise positions between the managed container and all children. - * This is called automatically when adding/inserting or removing children, - * but must be called manually if the managed container is manipulated - * outside of these methods (for example, if style properties change, or - * if it's resized). - */ - synchronise() { - if (this._frozen) { - return; - } - - let child; - for (child of this._children) { - if (!this._dnd.active || child !== this._dnd.child) { - child.synchroniseMaster(); - } - } - - for (child of this._children) { - if (!this._dnd.active || child !== this._dnd.child) { - child.synchroniseContainer(); - } - } - } - - shadowStyle = ` - :host { - position: relative; - display: block; - } - ` - - template = ` - - - ` -} - -customElements.define("gaia-container", GaiaContainer); diff --git a/src/components/control-center/header-bar.ts b/src/components/control-center/header-bar.ts deleted file mode 100644 index fd9be7f..0000000 --- a/src/components/control-center/header-bar.ts +++ /dev/null @@ -1,289 +0,0 @@ -import { html, css, LitElement, HTMLTemplateResult, nothing } from 'lit' -import { customElement, property, query, state } from 'lit/decorators.js' - -export enum HeaderBarType { - ONLY_TIME = 'only-time', - DATE_TIME = 'date-time' -} - -@customElement('header-bar') -export class HeaderBar extends LitElement { - @state() updateTimeTimeout!: number; - @state() updateDateTimeout!: number; - @property({type: HeaderBarType}) type = ''; - - @query('#time') time!: HTMLDivElement; - @query('#date') date!: HTMLDivElement; - - getTime(): HTMLTemplateResult { - return html` -
-
-
- -
-
- `; - } - - getTimeAndDate(): HTMLTemplateResult { - return html` -
-
-
-
-
-
- -
-
- `; - } - - render() { - switch (this.type) { - case HeaderBarType.ONLY_TIME: - return this.getTime(); - case HeaderBarType.DATE_TIME: - return this.getTimeAndDate(); - default: - console.error('unhandled 【header-bar】 type'); - return nothing; - } - } - - static styles = css` - :host { - --only-time-color-lm: #292929; - --only-time-color-dm: #F0F0F0; - --time-date-time-color-lm: #404040; - --time-date-date-color-lm: #000000; - --time-date-time-color-dm: #E0E0E0; - --time-date-date-color-dm: #E0E0E0; - width: inherit; - height: inherit; - } - - .time-outer { - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: space-between; - } - - .time-outer > #time { - height: 52px; - line-height: 52px; - font-family: OPPOSans; - font-style: normal; - font-weight: 400; - font-size: 52px; - color: var(--only-time-color-lm); - } - - .time-icons { - display: flex; - width: 136px; - position: relative; - right: 4px; - } - - .time-icons > ::slotted(*) { - display: flex; - } - - .time-icons > ::slotted(:last-child) { - position: relative; - left: 40px; - } - - .time-date-outer { - width: 100%; - height: 100%; - display: flex; - align-items: end; - } - - .time-date { - height: 100%; - width: 100%; - display: flex; - align-items: end; - line-height: 64px; - vertical-align: middle; - font-family: 'OPPOSans'; - font-style: normal; - font-weight: 400; - position: relative; - left: 10px; - } - - .time-date > #time { - color: var(--time-date-time-color-lm); - font-size: 64px; - } - - #date { - height: 34px; - line-height: 34px; - position: relative; - left: 22px; - font-size: 26px; - opacity: 0.6; - color: var(--time-date-date-color-lm); - mix-blend-mode: normal; - } - - .time-date-icons { - position: relative; - right: 11px; - } - - .host([deep-mode]) .time-outer > #time { - height: 52px; - line-height: 52px; - font-family: OPPOSans; - font-style: normal; - font-weight: 400; - font-size: 52px; - color: var(--only-time-color-dm); - } - - .host([deep-mode]) .time-date > #time { - color: var(--time-date-time-color-dm); - font-size: 64px; - } - - .host([deep-mode]) #date { - height: 34px; - line-height: 34px; - position: relative; - left: 22px; - font-size: 26px; - opacity: 0.6; - color: var(--time-date-date-color-dm); - mix-blend-mode: normal; - } - ` - - firstUpdated() { - this.autoUpdateDateTime(); - } - - autoUpdateDateTime() { - switch (this.type) { - case HeaderBarType.ONLY_TIME: - window.clearTimeout(this.updateTimeTimeout); - this.autoUpdateTime(); - break; - case HeaderBarType.DATE_TIME: - window.clearTimeout(this.updateDateTimeout); - window.clearTimeout(this.updateTimeTimeout); - this.autoUpdateDate(); - this.autoUpdateTime(); - break; - } - } - - autoUpdateTime() { - var d = new Date(); - this.time.innerHTML = this.formatTime(d); - let self = this; - var remainMillisecond = (60 - d.getSeconds()) * 1000; - this.updateTimeTimeout = window.setTimeout(() => { - self.autoUpdateTime(); - }, remainMillisecond); - } - - autoUpdateDate() { - var d = new Date(); - this.date.innerHTML = this.formatDate(d) + " " + this.getWeekDay(); - let remainMillisecond = (24 - d.getHours()) * 3600 * 1000 - - d.getMinutes() * 60 * 1000 - d.getMilliseconds(); - let self = this; - this.updateDateTimeout = window.setTimeout( - function updateDateTimeout() { - self.autoUpdateDate(); - }, remainMillisecond); - } - - getWeekDay() { - var d = new Date(); - let daynumber = d.getDay(); - let day = ""; - switch (daynumber) { - case 0: - day = "周日"; - break; - case 1: - day = "周一"; - break; - case 2: - day = "周二"; - break; - case 3: - day = "周三"; - break; - case 4: - day = "周四"; - break; - case 5: - day = "周五"; - break; - case 6: - day = "周六"; - break; - } - return day; - } - - formatDate(d: Date | string, iso?: boolean) { - if (d instanceof Date) { - if (iso) { - let date = d.toISOString(); // Thu Oct 07 2021 07:45:18 GMT+0800 - date = date.split("T")[0]; - return date; - } else { - return d.toLocaleString(navigator.languages as string[], { - // year: 'numeric', - month: 'long', - day: '2-digit', - }); - } - } else { - return d; - } - } - - formatTime(d: Date | string, iso?: boolean) { - if (d instanceof Date) { - if (iso) { - let time = d.toLocaleTimeString(); - time = time.split(" ")[0]; - if (time.indexOf(":") === 1) { - time = `0${time}`; - } - return time; - } else { - return d.toLocaleString(navigator.languages as string[], { - // hour12: (navigator as any).mozHour12, - hour12: false, - hour: "numeric", - minute: "numeric", - }); - } - } else { - if (d.indexOf(":") == 1) { - d = "0" + d; - } - return d; - } - } -} - -declare global { - interface HTMLElementTagNameMap { - 'header-bar': HeaderBar - } -} \ No newline at end of file diff --git a/src/components/control-center/icon-item.ts b/src/components/control-center/icon-item.ts deleted file mode 100644 index a3bdedd..0000000 --- a/src/components/control-center/icon-item.ts +++ /dev/null @@ -1,318 +0,0 @@ -import { html, css, LitElement, HTMLTemplateResult, nothing } from 'lit' -import { customElement, property, eventOptions, query, state } from 'lit/decorators.js' - -export enum IconType { - BASE = 'base', - BASE_WITHOUT_BORDER = 'base-without-border', - WITH_STATE = 'with-state' -} - -@customElement('icon-item') -export class IconItem extends LitElement { - @property({type: IconType}) type = ''; - @property({type: String}) icon = ''; - @property({type: String}) stateDesc = ''; - @property({type: String}) settingsKey = ''; - @property({type: Boolean}) bgchange = false; - @property({type: String}) id = ''; - @property({type: Boolean}) active = false; - @state({}) timer!: NodeJS.Timeout; - - @query('.more-info-icon') moreInfoIcon!: HTMLDivElement; - @query('.icon-button') iconBtn!: HTMLDivElement; - - getbase(): HTMLTemplateResult | typeof nothing { - if (!this.icon) { - console.error('【icon-item】缺少 icon 参数'); - return nothing; - } - - const iconstyle = html` - - `; - - return html ` -
- ${iconstyle} -
- `; - } - - getbaseWithOutBorder(): HTMLTemplateResult | typeof nothing { - if (!this.icon) { - console.error('【icon-item】缺少 icon 参数'); - return nothing; - } - - return html ` -
-
- `; - } - - getwithstate(): HTMLTemplateResult | typeof nothing { - if (!this.icon) { - console.error('【icon-item】缺少 icon 参数'); - return nothing; - } - - const iconstyle = html` - - `; - - return html` -
-

${this.stateDesc}

-
- ${iconstyle} -
- `; - } - - @eventOptions({passive: false}) - handleClick(event: Event) { - let isActive = true; // 闹铃 - if (this.bgchange) { - let target = event.target as HTMLElement; - if (target.nodeName == "P") { - target = target.parentElement as HTMLElement; - } - - if (target.className == "more-info-icon") { - target = target.parentElement as HTMLElement; - } - - isActive = target.classList.contains("active"); - this.activeOrInactive(isActive, target); - } - - // if (this.type == IconType.WITH_STATE) { - // if (target.className == "more-info-icon") { - // target = target.parentElement as HTMLElement; - // } - // if (target.classList.contains("active")) { - // this.moreInfoIcon.dataset.icon = "expand-left"; - // } else { - // this.moreInfoIcon.dataset.icon = ""; - // } - // } - - let self = this; - window.dispatchEvent(new CustomEvent("icon-item-click", { - detail: { - id: self.id ? self.id : self.icon, - isActive: isActive, - target: self - } - })); - } - - handleInfo() { - let self = this; - window.dispatchEvent(new CustomEvent("more-info-action", {detail: self.icon})); - } - - handlePress(event: Event) { - let target = event.target as HTMLElement; - if (target.nodeName == "P") { - target = target.parentElement as HTMLElement; - } - - if (this.getAttribute("disabled") === "true") { - return; - } - - let section = this.icon; - this.timer = setTimeout(() => { - let activity = new WebActivity("moz_configure_window", { - data: { - target: "device", - section: section - } - }); - activity.start(); - }, 300); - - let self = this; - window.dispatchEvent(new CustomEvent("touch-start", { - detail: { - id: self.id ? self.id : self.icon, - target: self - } - })); - } - - handlePressEnd() { - clearTimeout(this.timer); - } - - activeOrInactive(isActive: boolean, element?: HTMLElement) { - if (element == null) { - isActive ? this.iconBtn.classList.remove("active") : - this.iconBtn.classList.add("active"); - this.active = isActive; - } else { - isActive ? element.classList.remove("active") : - element.classList.add("active"); - } - } - - render(): HTMLTemplateResult | typeof nothing { - switch (this.type) { - case IconType.BASE: - return this.getbase(); - case IconType.BASE_WITHOUT_BORDER: - return this.getbaseWithOutBorder(); - case IconType.WITH_STATE: - return this.getwithstate(); - default: - console.error('unhandled 【icon-item】 type') - return nothing; - } - } - - addClass(className: string[]) { - this.iconBtn.classList.add(...className); - } - - removeClass(className: string) { - this.iconBtn.classList.remove(className); - } - - getClassList() { - return this.iconBtn.classList; - } - - static styles = css` - :host { - --background-active: #1D98F5; - --background-lm: rgba(255, 255, 255, 0.35); - --background-dm: rgba(0, 0, 0, 0.15); - --text-color-lm: #4D4D4D; - --text-color-dm: #D1D1D1; - --text-color-active: #FFFFFF; - } - - .active { - background-color: var(--background-active) !important; - color: var(--text-color-active) !important; - } - - .with-border { - width: 100%; - height: 100%; - display: flex; - align-items: center; - border-radius: 16px; - background: var(--background-lm); - } - - .icon-button::before { - width: 48px; - height: 48px; - line-height: 48px; - text-align: center; - vertical-align: middle; - content: attr(data-icon); - font-size: 48px; - font-family: gaia-icons; - font-style: normal; - text-rendering: optimizelegibility; - font-weight: 500; - } - - .icon-with-state::before { - position: relative; - left: 22px; - } - - .icon-base { - justify-content: center; - } - - .more-info-icon { - width: 16px; - height: 16px; - position: relative; - left: 58px; - } - - .more-info-icon::after { - width: 16px; - height: 16px; - text-align: center; - vertical-align: middle; - line-height: 16px; - content: attr(data-icon); - font-size: 16px; - font-family: gaia-icons; - font-style: normal; - text-rendering: optimizelegibility; - font-weight: 500; - } - - p { - width: 100px; - height: 20px; - position: relative; - left: 34px; - color: var(--text-color-lm); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - font-family: OPPOSans; - font-style: normal; - font-weight: 400; - font-size: 21px; - line-height: 20px; - mix-blend-mode: normal; - } - - .active > p { - color: var(--text-color-active); - } - - :host([deep-mode]) .with-border { - width: 100%; - height: 100%; - display: flex; - align-items: center; - border-radius: 16px; - // border-radius: 8px; - background: var(--background-dm); - } - - :host([deep-mode]) p { - width: 100px; - height: 20px; - position: relative; - left: 34px; - color: var(--text-color-dm); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - font-family: OPPOSans; - font-style: normal; - font-weight: 400; - font-size: 21px; - line-height: 20px; - mix-blend-mode: normal; - } - ` -} - -declare global { - interface HTMLElementTagNameMap { - 'icon-item': IconItem - } -} \ No newline at end of file diff --git a/src/components/control-center/icondb.ts b/src/components/control-center/icondb.ts deleted file mode 100644 index 580f7b0..0000000 --- a/src/components/control-center/icondb.ts +++ /dev/null @@ -1,88 +0,0 @@ -export default class IconDB { - db: any; - DB_NAME = 'icon-db'; - DB_ORDER_STORE = 'order'; - DB_VERSION = 1; - - init() { - return new Promise((resolve: (value: void) => void, reject) => { - var req = window.indexedDB.open(this.DB_NAME, this.DB_VERSION); - req.onupgradeneeded = this.upgradeSchema; - req.onsuccess = () => { - this.db = req.result; - resolve(); - }; - req.onerror = (e) => { - console.error('Error opening icon db', e); - reject(e); - }; - }); - } - - upgradeSchema(e: any) { - var db = e.target.result; - var fromVersion = e.oldVersion; - if (fromVersion < 1) { - var store = db.createObjectStore(this.DB_ORDER_STORE, { keyPath: 'id' }); - store.createIndex('order', 'order', { unique: false }); - } - } - - set(data: any) { - return new Promise((resolve, reject) => { - var txn = this.db.transaction(this.DB_ORDER_STORE, - 'readwrite'); - for (var entry of data) { - if (!entry.id) { - continue; - } - - if (typeof entry.order !== 'undefined') { - txn.objectStore(this.DB_ORDER_STORE). - put({ id: entry.id, order: entry.order }); - } - } - txn.oncomplete = resolve; - txn.onerror = reject; - }); - } - - remove(id: string) { - return new Promise((resolve, reject) => { - var txn = this.db.transaction(this.DB_ORDER_STORE, 'readwrite'); - txn.objectStore(this.DB_ORDER_STORE).delete(id); - txn.oncomplete = resolve; - txn.onerror = reject; - }); - } - - getAll(onResult: Function) { - return new Promise((resolve: (value?: any) => void) => { - try { - - var txn = this.db.transaction(this.DB_ORDER_STORE, 'readonly'); - var orderStore = txn.objectStore(this.DB_ORDER_STORE); - var cursor = orderStore.index('order').openCursor(); - var results: any[] = []; - - cursor.onsuccess = (e: any) => { - var cursor = e.target.result; - if (cursor) { - var result = cursor.value; - console.log("ffff result: ", result); - if (onResult) { - onResult(result); - } - cursor.continue(); - } - }; - - txn.oncomplete = () => { - resolve(results); - }; - } catch (error) { - resolve("error"); - } - }); - } -} \ No newline at end of file diff --git a/src/components/control-center/icons-one-line.ts b/src/components/control-center/icons-one-line.ts deleted file mode 100644 index b6a8fa1..0000000 --- a/src/components/control-center/icons-one-line.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { html, css, LitElement, HTMLTemplateResult, nothing } from 'lit' -import { customElement, property, queryAssignedElements } from 'lit/decorators.js' - -export enum IconsOneLineType { - BASE = 'base', - WITH_STATE = 'with-state' -} - -@customElement('icons-one-line') -export class IconsOneLine extends LitElement { - @property({type: IconsOneLineType}) type = ''; - @property({type: Number}) count = 2; - @queryAssignedElements({flatten: true}) slotElements!: HTMLSlotElement[]; - - getbase(): HTMLTemplateResult { - const colorstyle = this.count !== 4 - ? html` - - ` - : nothing; - return html` -
-
- -
- ${colorstyle} -
- `; - } - - getIconWithState(): HTMLTemplateResult { - return html` -
- -
- `; - } - - firstUpdated() { - this.count = this.slotElements.length; - } - - render() { - switch (this.type) { - case IconsOneLineType.BASE: - return this.getbase(); - case IconsOneLineType.WITH_STATE: - return this.getIconWithState(); - default: - console.error('unhandled 【icons-one-line】 type') - return nothing; - } - } - - static styles = css` - :host { - --background-lm: #FFFFFF; - --background-dm: #000000; - --opacity-lm: 0.75; - --opacity-dm: 0.25; - --line-border-lm: rgba(0, 0, 0, 0.07); - --line-border-dm: rgba(255, 255, 255, 0.07); - - width: inherit; - height: inherit; - background: var(--background-lm); - mix-blend-mode: normal; - opacity: var(--opacity-lm); - border-radius: 16px; - } - - .icon-with-state { - width: 100%; - display: flex; - align-items: center; - // justify-content: space-around; - justify-content: space-between; - } - - .icon-only { - width: inherit; - height: inherit; - background: inherit; - border-radius: inherit; - opacity: inherit; - } - - .icon-only > div { - display: flex; - align-items: center; - height: 100%; - } - - .icon-only > div > ::slotted(*) { - width: 25%; - height: 30px; - display: flex; - align-items: center; - justify-content: center; - border-left: 2px solid var(--line-border-lm); - border-radius: 2px; - } - - .icon-only > div > ::slotted(:first-child) { - border-left-style: none; - } - - :host([deep-mode]) { - width: inherit; - height: inherit; - background: var(--background-dm); - mix-blend-mode: normal; - opacity: var(--opacity-dm); - border-radius: 16px; - } - - :host([deep-mode]) .icon-only > div > ::slotted(*) { - width: 25%; - height: 30px; - display: flex; - align-items: center; - justify-content: center; - border-left: 2px solid var(--line-border-dm); - border-radius: 2px; - } - ` -} - -declare global { - interface HTMLElementTagNameMap { - 'icons-one-line': IconsOneLine - } -} \ No newline at end of file diff --git a/src/components/control-center/index.ts b/src/components/control-center/index.ts deleted file mode 100644 index baeddc1..0000000 --- a/src/components/control-center/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './control-center-bar.js' \ No newline at end of file diff --git a/src/components/control-center/light-slider.ts b/src/components/control-center/light-slider.ts deleted file mode 100644 index 84284d6..0000000 --- a/src/components/control-center/light-slider.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { html, css, LitElement, HTMLTemplateResult } from 'lit' -import { customElement, property, query } from 'lit/decorators.js' -@customElement('light-slider') -export class LightSlider extends LitElement { - @query('.progress') progress!: HTMLDivElement; - @query('.sliderBar') sliderBar!: HTMLDivElement; - @property({type: String}) id = ''; - @property({type: String}) _coverLen = ''; - @property({type: Number}) innerWidth = 0; - @property({type: Number}) distance = 0; - @property({type: Number}) currentDistance = 0; - @property({type: Number}) barWidth = 0; - @property({type: Number}) max = 100; - @property({type: Number}) value = 1; - @property() touchAction = { - // 触摸开始落点 - start: { - offsetX: 0, - offsetY: 0, - clientX: 0, - clientY: 0 - }, - - // 触摸结束落点 - last: { - offsetX: 0, - offsetY: 0, - clientX: 0, - clientY: 0 - } - } - - @property({type: String}) - get coverLen() { - return this._coverLen; - } - - set coverLen(value: string) { - this.style.setProperty('--cover-length', value); - this._coverLen = value; - } - - render(): HTMLTemplateResult { - return html` -
-
-
- ` - } - - static styles = css` - :host { - width: inherit; - height: inherit; - dislay: block; - --cover-length: 3.78px; // 亮度为1 - --background-lm: rgba(255, 255, 255, 0.5); - --background-dm: rgba(0, 0, 0, 0.15); - --progress-background-lm: rgba(255, 255, 255, 0.8); - --progress-background-dm: rgba(255, 255, 255, 0.7); - } - - .sliderBar { - width: inherit; - height: inherit; - position: absolute; - left: 0px; - right: 0px; - background: var(--background-lm); - border-radius: 16px; - } - - .progress { - width: var(--cover-length); - height: 100%; - position: absolute; - left: 0px; - right: 0px; - background: var(--progress-background-lm); - border-radius: 16px; - } - - .sliderBar::before { - position: absolute; - width: 48px; - height: 48px; - left: 29px; - top: 29px; - content: attr(data-icon); - font-size: 48px; - font-family: gaia-icons; - font-style: normal; - text-rendering: optimizelegibility; - font-weight: 500; - } - ` - - firstUpdated() { - if (this.value) { - let len = Math.floor(this.value * this.sliderBar.offsetWidth / this.max); - this.coverLen = len.toString(); - } - } - - handleEvent(event: TouchEvent) { - switch (event.type) { - case "touchstart": - this.touchAction.start.clientX = event.touches[0].clientX; - this.barWidth = this.sliderBar.offsetWidth; - break; - case "touchmove": - this.touchAction.last.clientX = event.touches[0].clientX; - this.distance = this.touchAction.last.clientX - this.touchAction.start.clientX; - this.currentDistance = this.distance + this.progress.offsetWidth; - - if (this.currentDistance < 0) { - // this.currentDistance = 0; - this.currentDistance = this.barWidth / this.max; - } - - if (this.currentDistance > this.barWidth) { - this.currentDistance = this.barWidth; - } - this.progress.style.setProperty('width', this.currentDistance + 'px'); - break; - case "touchend": - this.value = Math.floor(this.currentDistance * this.max / this.barWidth); - this.dispatchEvent(new CustomEvent("light-slider-change", { - detail: { - value: this.value - }, - bubbles: true, - composed: true, - })); - break; - } - } - - setValue(value: number) { - console.log("light00 set value: ", value); - this.value = value; - console.log("light00 set this.value: ", this.value); - let len = Math.floor(value * this.sliderBar.offsetWidth / this.max); - this.coverLen = len.toString(); - console.log("light00 set this.coverLen: ", this.coverLen); - } -} - -declare global { - interface HTMLElementTagNameMap { - 'light-slider': LightSlider - } -} \ No newline at end of file diff --git a/src/components/control-center/mock_settings_observer.ts b/src/components/control-center/mock_settings_observer.ts deleted file mode 100644 index 5b35f23..0000000 --- a/src/components/control-center/mock_settings_observer.ts +++ /dev/null @@ -1,88 +0,0 @@ -interface Obj { - name?: string; - value?: any; - callback: (name: string, value: any)=> void; -} - -interface Pair { - name: string; - value: any; -} - - -export var settingsObserver = { - _keyvaluepairs: [] as Pair[], // 存放设定的设置键值对 - _observers: [] as Obj[], // 存放observe方法存入的 - - getValue: function(name: string) { - // return new Promise((resolve: (value: any) => void) => { - // resolve(true); - // }) - - return new Promise(resovle => { - let value; - this._keyvaluepairs.forEach((pair: any) => { - if(pair.name == name) { - value = pair.value; - } - }); - return resovle(value); - }) - }, - - observe: function(name: string, defaultValue: any, callback: (name: string, value: any)=> void, observeOnly: boolean) { - if (!observeOnly) { - this.getValue(name).then((value) => { - callback(name, value !== null && value !== void 0 ? value : defaultValue); // 重启前设置值为false或0时,重启后返回的值不应该为默认值 - }); - } - this._observers.push({ - name, - callback - }); - }, - - setValue: function(args: any[]) { - return new Promise((resovle: (value: void)=> void) => { - // 将传入的设置值更新/设置入_keyvaluepairs - args.forEach((pair: any) => { - let targetPair = this._keyvaluepairs.find((item: any) => { - return item.name == pair.name - }); - if (targetPair as any) { - // 在_keyvaluepairs根据pair.name找到了相同的设置值,更新键值对的value - (targetPair as any).value = pair.value; - } else { - // 在_keyvaluepairs不存在该设置值,新增键值对 - let newPair = { - name: pair.name, - value: pair.value - }; - this._keyvaluepairs.push(newPair); - } - - // 同时检查_observers中是否有该设置值变化时的回调 - this._observers.forEach(ob => { - ob.name = pair.name && ob.callback?.(pair.name, pair.value); - }); - - resovle(); - }); - }) - }, - - getBatch: function (names: string[]) { - return new Promise((resolve: ({}) => void) => { - let result = []; - for (let index = 0; index < names.length; index++) { - const name = names[index]; - let value = true; - result.push({name, value: value}); - } - - if (result.length == names.length) { - resolve(result); - } - }) - } -} \ No newline at end of file diff --git a/src/components/control-center/package.json b/src/components/control-center/package.json deleted file mode 100644 index 88694f8..0000000 --- a/src/components/control-center/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "@star-web-components/control-center-bar", - "version": "0.0.1", - "description": "", - "type": "module", - "main": "./index.js", - "module": "./index.js", - "exports": { - ".": { - "default": "./index.js" - }, - "./index": { - "default": "./index.js" - }, - "./icon-item.js": { - "default": "./icon-item.js" - }, - "./icons-one-line.js": { - "default": "./icons-one-line.js" - }, - "./header-bar.js": { - "default": "./header-bar.js" - }, - "./light-slider.js": { - "default": "./light-slider.js" - }, - "./pull-down-menu.js": { - "default": "./pull-down-menu.js" - }, - "./control-center-bar.js": { - "default": "./control-center-bar.js" - }, - "./package.json": "./package.json" - }, - "author": "", - "license": "ISC" -} diff --git a/src/components/control-center/pull-down-menu.ts b/src/components/control-center/pull-down-menu.ts deleted file mode 100644 index 0007283..0000000 --- a/src/components/control-center/pull-down-menu.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { html, css, LitElement, HTMLTemplateResult, nothing } from 'lit' -import { customElement, property, queryAssignedElements } from 'lit/decorators.js' -import { HeaderBarType } from './header-bar'; -import { IconItem, IconType } from './icon-item'; -import './icon-item'; -import './header-bar'; -export enum PullDownMenuType { - HEADER_WITH_TIME = 'header-with-time', - HEADER_WITH_DATE_TIME = 'header-with-date-time' -} - -@customElement('pull-down-menu') -export class PullDownMenu extends LitElement { - @property({type: PullDownMenuType}) type = ''; - @queryAssignedElements({flatten: true}) slotElements!: HTMLSlotElement[]; - getOnlyTime(): HTMLTemplateResult { - return html` -
- - - - -
- -
-
- ` - } - - getTimeAndDate(): HTMLTemplateResult { - return html` -
- - - -
- -
-
- ` - } - - render(): HTMLTemplateResult | typeof nothing { - switch (this.type) { - case PullDownMenuType.HEADER_WITH_TIME: - return this.getOnlyTime(); - case PullDownMenuType.HEADER_WITH_DATE_TIME: - return this.getTimeAndDate(); - default: - console.error('unhandled 【pull-down-menu】 type'); - return nothing; - } - } - - static styles = css` - :host { - width: inherit; - height: inherit; - position: absolute; - left: 0px; - top: 0px; - } - - :host([open]) { - transform: translateY(0); - transition: transform 300ms ease, visibility 300ms; - will-change: transform; - visibility: visible; - } - - .inner { - width: inherit; - height: inherit; - display: flex; - flex-direction: column; - align-items: center; - } - - header-bar[type='only-time'] { - dispaly: flex; - width: 512px; - height: 52px; - } - - header-bar[type='date-time'] { - dispaly: flex; - width: 860px; - height: 64px; - } - - .all-quick-icons { - width: 100%; - height: calc(100% - 52px); - position: relative; - top: 40px; - } - - .others { - display: flex; - flex-direction: column; - position: absolute; - top: 100px; - } - ` - - handleEvent(event: Event) { - switch (event.type) { - case "click": - switch ((event.target as IconItem).icon) { - case "compose": - window.dispatchEvent(new CustomEvent("editor-action")); - break; - case "settings": - let activity = new WebActivity("configure", {}); - activity.start().then(() => {}, () => {}); - break; - } - break; - } - - } -} - -declare global { - interface HTMLElementTagNameMap { - 'pull-down-menu': PullDownMenu - } -} \ No newline at end of file diff --git a/src/components/drop-down-menu/drop-down-menu.ts b/src/components/drop-down-menu/drop-down-menu.ts new file mode 100644 index 0000000..ac578a5 --- /dev/null +++ b/src/components/drop-down-menu/drop-down-menu.ts @@ -0,0 +1,173 @@ +import {html, css, LitElement, HTMLTemplateResult, nothing} from 'lit' +import {customElement, property, queryAssignedElements} from 'lit/decorators.js' +import {HeaderBarType} from '../header-bar/header-bar.js' +import {IconControlBar, IconControlBarType} from '../icon-control-bar/icon-control-bar.js' +import {WebActivity} from './interface.js' +import '../icon-control-bar/icon-control-bar.js' +import '../header-bar/header-bar.js' +export enum DropDownMenuType { + HEADER_WITH_TIME = 'header-with-time', + HEADER_WITH_DATE_TIME = 'header-with-date-time', +} + +@customElement('pull-down-menu') +export class DropDownMenu extends LitElement { + @property({type: DropDownMenuType}) type = '' + @queryAssignedElements({flatten: true}) slotElements!: HTMLSlotElement[] + getOnlyTime(): HTMLTemplateResult { + return html` +
+ + + + +
+ +
+
+ ` + } + + getTimeAndDate(): HTMLTemplateResult { + return html` +
+ + + +
+ +
+
+ ` + } + + render(): HTMLTemplateResult | typeof nothing { + switch (this.type) { + case DropDownMenuType.HEADER_WITH_TIME: + return this.getOnlyTime() + case DropDownMenuType.HEADER_WITH_DATE_TIME: + return this.getTimeAndDate() + default: + console.error('unhandled 【pull-down-menu】 type') + return nothing + } + } + + static styles = css` + :host { + width: inherit; + height: inherit; + position: absolute; + left: 0px; + top: 0px; + } + + :host([open]) { + transform: translateY(0); + transition: transform 300ms ease, visibility 300ms; + will-change: transform; + visibility: visible; + } + + .inner { + width: inherit; + height: inherit; + display: flex; + flex-direction: column; + align-items: center; + } + + @media screen and (max-width: 1200px) { + header-bar[type='only-time'] { + dispaly: flex; + width: 512px; + height: 52px; + } + + header-bar[type='date-time'] { + dispaly: flex; + width: 860px; + height: 64px; + } + + .all-quick-icons { + width: 100%; + height: calc(100% - 52px); + position: relative; + top: 40px; + } + + .others { + display: flex; + flex-direction: column; + position: absolute; + top: 100px; + } + } + + @media screen and (max-width: 600px) { + header-bar[type='only-time'] { + dispaly: flex; + width: 256px; + height: 26px; + } + + header-bar[type='date-time'] { + dispaly: flex; + width: 430px; + height: 32px; + } + + .all-quick-icons { + width: 100%; + height: calc(100% - 26px); + position: relative; + top: 20px; + } + + .others { + display: flex; + flex-direction: column; + position: absolute; + top: 50px; + } + } + ` + + handleEvent(event: Event) { + switch (event.type) { + case 'click': + switch ((event.target as IconControlBar).icon) { + case 'compose': + window.dispatchEvent(new CustomEvent('editor-action')) + break + case 'settings': + let activity = new WebActivity('configure', {}) + activity.start().then( + () => {}, + () => {} + ) + break + } + break + } + } +} + +declare global { + interface HTMLElementTagNameMap { + 'pull-down-menu': DropDownMenu + } +} diff --git a/src/components/drop-down-menu/index.ts b/src/components/drop-down-menu/index.ts new file mode 100644 index 0000000..cb457f9 --- /dev/null +++ b/src/components/drop-down-menu/index.ts @@ -0,0 +1 @@ +export * from './drop-down-menu.js' diff --git a/src/components/drop-down-menu/interface.ts b/src/components/drop-down-menu/interface.ts new file mode 100644 index 0000000..37700c0 --- /dev/null +++ b/src/components/drop-down-menu/interface.ts @@ -0,0 +1,9 @@ +export interface WebActivity { + start(): Promise + cancel(): void +} + +export var WebActivity: { + prototype: WebActivity + new (name: string, data?: any): WebActivity +} diff --git a/src/components/drop-down-menu/package.json b/src/components/drop-down-menu/package.json new file mode 100644 index 0000000..3e0b385 --- /dev/null +++ b/src/components/drop-down-menu/package.json @@ -0,0 +1,22 @@ +{ + "name": "@star-web-components/drop-down-menu", + "version": "0.0.1", + "description": "", + "type": "module", + "main": "./index.js", + "module": "./index.js", + "exports": { + ".": { + "default": "./index.js" + }, + "./index": { + "default": "./index.js" + }, + "./drop-down-menu.js": { + "default": "./drop-down-menu.js" + }, + "./package.json": "./package.json" + }, + "author": "", + "license": "ISC" +} diff --git a/src/components/drop-down-menu/tsconfig.json b/src/components/drop-down-menu/tsconfig.json new file mode 100644 index 0000000..f21b075 --- /dev/null +++ b/src/components/drop-down-menu/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "composite": true, + "rootDir": "../../" + }, + "include": [ + "*.ts", + "../icon-control-bar/icon-control-bar.js", + "../header-bar/header-bar.js", + "./interface.js" + ] +} diff --git a/src/components/header-bar/header-bar.ts b/src/components/header-bar/header-bar.ts new file mode 100644 index 0000000..66351e4 --- /dev/null +++ b/src/components/header-bar/header-bar.ts @@ -0,0 +1,327 @@ +import {html, css, LitElement, HTMLTemplateResult, nothing} from 'lit' +import {customElement, property, query, state} from 'lit/decorators.js' + +export enum HeaderBarType { + ONLY_TIME = 'only-time', + DATE_TIME = 'date-time', +} + +@customElement('header-bar') +export class HeaderBar extends LitElement { + @state() updateTimeTimeout!: number + @state() updateDateTimeout!: number + @property({type: HeaderBarType}) type = '' + + @query('#time') time!: HTMLDivElement + @query('#date') date!: HTMLDivElement + + getTime(): HTMLTemplateResult { + return html` +
+
+
+ +
+
+ ` + } + + getTimeAndDate(): HTMLTemplateResult { + return html` +
+
+
+
+
+
+ +
+
+ ` + } + + render() { + switch (this.type) { + case HeaderBarType.ONLY_TIME: + return this.getTime() + case HeaderBarType.DATE_TIME: + return this.getTimeAndDate() + default: + console.error('unhandled 【header-bar】 type') + return nothing + } + } + + static styles = css` + :host { + --only-time-color-lm: #292929; + --only-time-color-dm: #f0f0f0; + --time-date-time-color-lm: #404040; + --time-date-date-color-lm: #000000; + --time-date-time-color-dm: #e0e0e0; + --time-date-date-color-dm: #e0e0e0; + width: inherit; + height: inherit;; + } + + .time-outer { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: space-between; + } + + .time-outer > #time { + font-family: OPPOSans; + font-style: normal; + font-weight: 400; + color: var(--only-time-color-lm); + } + + .time-icons > ::slotted(*) { + display: flex; + } + + .time-date-outer { + width: 100%; + height: 100%; + display: flex; + align-items: end; + } + + .time-date { + height: 100%; + width: 100%; + display: flex; + align-items: end; + vertical-align: middle; + font-family: 'OPPOSans'; + font-style: normal; + font-weight: 400; + position: relative; + } + + .time-date > #time { + color: var(--time-date-time-color-lm); + } + + #date { + position: relative; + opacity: 0.6; + color: var(--time-date-date-color-lm); + mix-blend-mode: normal; + } + + .host([deep-mode]) .time-outer > #time { + color: var(--only-time-color-dm); + } + + .host([deep-mode]) #date { + color: var(--time-date-date-color-dm); + } + + @media screen and (max-width: 1200px) { + .time-outer > #time { + height: 52px; + line-height: 52px; + font-size: 52px; + } + + .time-icons { + display: flex; + width: 136px; + position: relative; + right: 4px; + } + + .time-icons > ::slotted(:last-child) { + position: relative; + left: 40px; + } + + .time-date { + line-height: 64px; + left: 10px; + } + + .time-date > #time { + font-size: 64px; + } + + #date { + height: 34px; + line-height: 34px; + left: 22px; + font-size: 26px; + } + + .time-date-icons { + position: relative; + right: 11px; + } + } + + @media screen and (max-width: 600px) { + .time-outer > #time { + height: 26px; + line-height: 26px; + font-size: 26px; + } + + .time-icons { + display: flex; + width: 68px; + position: relative; + right: 2px; + } + + .time-icons > ::slotted(:last-child) { + position: relative; + left: 20px; + } + + .time-date { + line-height: 32px; + left: 5px; + } + + .time-date > #time { + font-size: 32px; + } + + #date { + height: 17px; + line-height: 17px; + left: 11px; + font-size: 13px; + } + + .time-date-icons { + position: relative; + right: 5.5px; + } + } + ` + + firstUpdated() { + this.autoUpdateDateTime() + } + + autoUpdateDateTime() { + switch (this.type) { + case HeaderBarType.ONLY_TIME: + window.clearTimeout(this.updateTimeTimeout) + this.autoUpdateTime() + break + case HeaderBarType.DATE_TIME: + window.clearTimeout(this.updateDateTimeout) + window.clearTimeout(this.updateTimeTimeout) + this.autoUpdateDate() + this.autoUpdateTime() + break + } + } + + autoUpdateTime() { + var d = new Date() + this.time.innerHTML = this.formatTime(d) + let self = this + var remainMillisecond = (60 - d.getSeconds()) * 1000 + this.updateTimeTimeout = window.setTimeout(() => { + self.autoUpdateTime() + }, remainMillisecond) + } + + autoUpdateDate() { + var d = new Date() + this.date.innerHTML = this.formatDate(d) + ' ' + this.getWeekDay() + let remainMillisecond = + (24 - d.getHours()) * 3600 * 1000 - + d.getMinutes() * 60 * 1000 - + d.getMilliseconds() + let self = this + this.updateDateTimeout = window.setTimeout(function updateDateTimeout() { + self.autoUpdateDate() + }, remainMillisecond) + } + + getWeekDay() { + var d = new Date() + let daynumber = d.getDay() + let day = '' + switch (daynumber) { + case 0: + day = '周日' + break + case 1: + day = '周一' + break + case 2: + day = '周二' + break + case 3: + day = '周三' + break + case 4: + day = '周四' + break + case 5: + day = '周五' + break + case 6: + day = '周六' + break + } + return day + } + + formatDate(d: Date | string, iso?: boolean) { + if (d instanceof Date) { + if (iso) { + let date = d.toISOString() // Thu Oct 07 2021 07:45:18 GMT+0800 + date = date.split('T')[0] + return date + } else { + return d.toLocaleString(navigator.languages as string[], { + // year: 'numeric', + month: 'long', + day: '2-digit', + }) + } + } else { + return d + } + } + + formatTime(d: Date | string, iso?: boolean) { + if (d instanceof Date) { + if (iso) { + let time = d.toLocaleTimeString() + time = time.split(' ')[0] + if (time.indexOf(':') === 1) { + time = `0${time}` + } + return time + } else { + return d.toLocaleString(navigator.languages as string[], { + // hour12: (navigator as any).mozHour12, + hour12: false, + hour: 'numeric', + minute: 'numeric', + }) + } + } else { + if (d.indexOf(':') == 1) { + d = '0' + d + } + return d + } + } +} + +declare global { + interface HTMLElementTagNameMap { + 'header-bar': HeaderBar + } +} diff --git a/src/components/header-bar/index.ts b/src/components/header-bar/index.ts new file mode 100644 index 0000000..313d237 --- /dev/null +++ b/src/components/header-bar/index.ts @@ -0,0 +1 @@ +export * from './header-bar.js' diff --git a/src/components/header-bar/package.json b/src/components/header-bar/package.json new file mode 100644 index 0000000..5b338bb --- /dev/null +++ b/src/components/header-bar/package.json @@ -0,0 +1,22 @@ +{ + "name": "@star-web-components/header-bar", + "version": "0.0.1", + "description": "", + "type": "module", + "main": "./index.js", + "module": "./index.js", + "exports": { + ".": { + "default": "./index.js" + }, + "./index": { + "default": "./index.js" + }, + "./header-bar.js": { + "default": "./header-bar.js" + }, + "./package.json": "./package.json" + }, + "author": "", + "license": "ISC" +} diff --git a/src/components/header-bar/tsconfig.json b/src/components/header-bar/tsconfig.json new file mode 100644 index 0000000..4ba3e2c --- /dev/null +++ b/src/components/header-bar/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "composite": true, + "rootDir": "../../" + }, + "include": ["*.ts"] +} diff --git a/src/components/icon-control-bar-group/icon-control-bar-group.ts b/src/components/icon-control-bar-group/icon-control-bar-group.ts new file mode 100644 index 0000000..0b3492b --- /dev/null +++ b/src/components/icon-control-bar-group/icon-control-bar-group.ts @@ -0,0 +1,170 @@ +import {html, css, LitElement, HTMLTemplateResult, nothing} from 'lit' +import {customElement, property, queryAssignedElements} from 'lit/decorators.js' + +export enum IconControlBarGroupType { + BASE = 'base', + WITH_STATE = 'with-state', +} + +@customElement('icon-control-bar-group') +export class IconControlBarGroup extends LitElement { + @property({type: IconControlBarGroupType}) type = '' + @property({type: Number}) count = 2 + @queryAssignedElements({flatten: true}) slotElements!: HTMLSlotElement[] + + getbase(): HTMLTemplateResult { + const colorstyle = + this.count !== 4 + ? html` + + ` + : nothing + return html` +
+
+ +
+ ${colorstyle} +
+ ` + } + + getIconWithState(): HTMLTemplateResult { + return html` +
+ +
+ ` + } + + firstUpdated() { + this.count = this.slotElements.length + } + + render() { + switch (this.type) { + case IconControlBarGroupType.BASE: + return this.getbase() + case IconControlBarGroupType.WITH_STATE: + return this.getIconWithState() + default: + console.error('unhandled 【icon-control-bar-group】 type') + return nothing + } + } + + static styles = css` + :host { + --background-lm: #ffffff; + --background-dm: #000000; + --opacity-lm: 0.75; + --opacity-dm: 0.25; + --line-border-lm: rgba(0, 0, 0, 0.07); + --line-border-dm: rgba(255, 255, 255, 0.07); + + width: inherit; + height: inherit; + background: var(--background-lm); + mix-blend-mode: normal; + opacity: var(--opacity-lm); + } + + .icon-with-state { + width: 100%; + display: flex; + align-items: center; + // justify-content: space-around; + justify-content: space-between; + } + + .icon-only { + width: inherit; + height: inherit; + background: inherit; + border-radius: inherit; + opacity: inherit; + } + + .icon-only > div { + display: flex; + align-items: center; + height: 100%; + } + + .icon-only > div > ::slotted(*) { + width: 25%; + height: 30px; + display: flex; + align-items: center; + justify-content: center; + } + + .icon-only > div > ::slotted(:first-child) { + border-left-style: none; + } + + :host([deep-mode]) { + background: var(--background-dm); + } + + // :host([deep-mode]) .icon-only > div > ::slotted(*) { + // width: 25%; + // // height: 30px; + // display: flex; + // align-items: center; + // justify-content: center; + // // border-left: 2px solid var(--line-border-dm); + // // border-radius: 2px; + // } + + @media screen and (max-width: 1200px) { + :host { + border-radius: 16px; + } + + .icon-only > div > ::slotted(*) { + height: 30px; + border-left: 2px solid var(--line-border-lm); + border-radius: 2px; + } + + :host([deep-mode]) { + border-radius: 16px; + } + + :host([deep-mode]) .icon-only > div > ::slotted(*) { + border-left: 2px solid var(--line-border-dm); + } + } + + @media screen and (max-width: 600px) { + :host { + border-radius: 8px; + } + + .icon-only > div > ::slotted(*) { + height: 15px; + border-left: 1px solid var(--line-border-lm); + border-radius: 1px; + } + + :host([deep-mode]) { + border-radius: 8px; + } + + :host([deep-mode]) .icon-only > div > ::slotted(*) { + border-left: 1px solid var(--line-border-dm); + } + } + ` +} + +declare global { + interface HTMLElementTagNameMap { + 'icon-control-bar-group': IconControlBarGroup + } +} diff --git a/src/components/icon-control-bar-group/index.ts b/src/components/icon-control-bar-group/index.ts new file mode 100644 index 0000000..0ea90fc --- /dev/null +++ b/src/components/icon-control-bar-group/index.ts @@ -0,0 +1 @@ +export * from './icon-control-bar-group.js' diff --git a/src/components/icon-control-bar-group/package.json b/src/components/icon-control-bar-group/package.json new file mode 100644 index 0000000..d6e21f0 --- /dev/null +++ b/src/components/icon-control-bar-group/package.json @@ -0,0 +1,22 @@ +{ + "name": "@star-web-components/icon-control-bar-group", + "version": "0.0.1", + "description": "", + "type": "module", + "main": "./index.js", + "module": "./index.js", + "exports": { + ".": { + "default": "./index.js" + }, + "./index": { + "default": "./index.js" + }, + "./icon-control-bar-group.js": { + "default": "./icon-control-bar-group.js" + }, + "./package.json": "./package.json" + }, + "author": "", + "license": "ISC" +} diff --git a/src/components/icon-control-bar-group/tsconfig.json b/src/components/icon-control-bar-group/tsconfig.json new file mode 100644 index 0000000..4ba3e2c --- /dev/null +++ b/src/components/icon-control-bar-group/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "composite": true, + "rootDir": "../../" + }, + "include": ["*.ts"] +} diff --git a/src/components/icon-control-bar/icon-control-bar.ts b/src/components/icon-control-bar/icon-control-bar.ts new file mode 100644 index 0000000..7fba0c1 --- /dev/null +++ b/src/components/icon-control-bar/icon-control-bar.ts @@ -0,0 +1,426 @@ +import {html, css, LitElement, HTMLTemplateResult, nothing} from 'lit' +import { + customElement, + property, + eventOptions, + query, + state, +} from 'lit/decorators.js' +import {WebActivity} from './interface.js' + +export enum IconControlBarType { + BASE = 'base', + BASE_WITHOUT_BORDER = 'base-without-border', + WITH_STATE = 'with-state', +} + +@customElement('icon-control-bar') +export class IconControlBar extends LitElement { + @property({type: IconControlBarType}) type = '' + @property({type: String}) icon = '' + @property({type: String}) stateDesc = '' + @property({type: String}) settingsKey = '' + @property({type: Boolean}) bgchange = false + @property({type: String}) id = '' + @property({type: Boolean}) active = false + @state({}) timer!: NodeJS.Timeout + + @query('.more-info-icon') moreInfoIcon!: HTMLDivElement + @query('.icon-button') iconBtn!: HTMLDivElement + + getbase(): HTMLTemplateResult | typeof nothing { + if (!this.icon) { + console.error('【icon-control-bar】缺少 icon 参数') + return nothing + } + + const iconstyle = html` + + ` + + return html` +
+ ${iconstyle} +
+ ` + } + + getbaseWithOutBorder(): HTMLTemplateResult | typeof nothing { + if (!this.icon) { + console.error('【icon-control-bar】缺少 icon 参数') + return nothing + } + + return html` +
+ ` + } + + getwithstate(): HTMLTemplateResult | typeof nothing { + if (!this.icon) { + console.error('【icon-control-bar】缺少 icon 参数') + return nothing + } + + const iconstyle = html` + + ` + + return html` +
+

${this.stateDesc}

+
+ ${iconstyle} +
+ ` + } + + @eventOptions({passive: false}) + handleClick(event: Event) { + let isActive = true // 闹铃 + if (this.bgchange) { + let target = event.target as HTMLElement + if (target.nodeName == 'P') { + target = target.parentElement as HTMLElement + } + + if (target.className == 'more-info-icon') { + target = target.parentElement as HTMLElement + } + + isActive = target.classList.contains('active') + this.activeOrInactive(isActive, target) + } + + // if (this.type == IconControlBarType.WITH_STATE) { + // if (target.className == "more-info-icon") { + // target = target.parentElement as HTMLElement; + // } + // if (target.classList.contains("active")) { + // this.moreInfoIcon.dataset.icon = "expand-left"; + // } else { + // this.moreInfoIcon.dataset.icon = ""; + // } + // } + + let self = this + window.dispatchEvent( + new CustomEvent('icon-control-bar-click', { + detail: { + id: self.id ? self.id : self.icon, + isActive: isActive, + target: self, + }, + }) + ) + } + + handleInfo() { + let self = this + window.dispatchEvent( + new CustomEvent('more-info-action', {detail: self.icon}) + ) + } + + handlePress(event: Event) { + let target = event.target as HTMLElement + if (target.nodeName == 'P') { + target = target.parentElement as HTMLElement + } + + if (this.getAttribute('disabled') === 'true') { + return + } + + let section = this.icon + this.timer = setTimeout(() => { + let activity = new WebActivity('moz_configure_window', { + data: { + target: 'device', + section: section, + }, + }) + activity.start() + }, 300) + + let self = this + window.dispatchEvent( + new CustomEvent('touch-start', { + detail: { + id: self.id ? self.id : self.icon, + target: self, + }, + }) + ) + } + + handlePressEnd() { + clearTimeout(this.timer) + } + + activeOrInactive(isActive: boolean, element?: HTMLElement) { + if (element == null) { + isActive + ? this.iconBtn.classList.remove('active') + : this.iconBtn.classList.add('active') + this.active = isActive + } else { + isActive + ? element.classList.remove('active') + : element.classList.add('active') + } + } + + render(): HTMLTemplateResult | typeof nothing { + switch (this.type) { + case IconControlBarType.BASE: + return this.getbase() + case IconControlBarType.BASE_WITHOUT_BORDER: + return this.getbaseWithOutBorder() + case IconControlBarType.WITH_STATE: + return this.getwithstate() + default: + console.error('unhandled 【icon-control-bar】 type') + return nothing + } + } + + addClass(className: string[]) { + this.iconBtn.classList.add(...className) + } + + removeClass(className: string) { + this.iconBtn.classList.remove(className) + } + + getClassList() { + return this.iconBtn.classList + } + + static styles = css` + :host { + --background-active: #1d98f5; + --background-lm: rgba(255, 255, 255, 0.35); + --background-dm: rgba(0, 0, 0, 0.15); + --text-color-lm: #4d4d4d; + --text-color-dm: #d1d1d1; + --text-color-active: #ffffff; + } + + .active { + background-color: var(--background-active) !important; + color: var(--text-color-active) !important; + } + + .with-border { + width: 100%; + height: 100%; + display: flex; + align-items: center; + background: var(--background-lm); + } + + .icon-button::before { + text-align: center; + vertical-align: middle; + content: attr(data-icon); + font-family: gaia-icons; + font-style: normal; + text-rendering: optimizelegibility; + font-weight: 500; + } + + .icon-base { + justify-content: center; + } + + .more-info-icon::after { + text-align: center; + vertical-align: middle; + content: attr(data-icon); + font-family: gaia-icons; + font-style: normal; + text-rendering: optimizelegibility; + font-weight: 500; + } + + p { + position: relative; + color: var(--text-color-lm); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + font-family: OPPOSans; + font-style: normal; + mix-blend-mode: normal; + } + + .active > p { + color: var(--text-color-active); + } + + :host([deep-mode]) .with-border { + background: var(--background-dm); + } + + :host([deep-mode]) p { + position: relative; + color: var(--text-color-dm); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + font-family: OPPOSans; + font-style: normal; + font-weight: 400; + mix-blend-mode: normal; + } + + + @media screen and (max-width: 600px) { + .with-border { + border-radius: 8px; + } + + .icon-button::before { + width: 24px; + height: 24px; + line-height: 24px; + font-size: 24px; + } + + .icon-with-state::before { + position: relative; + left: 11px; + } + + .more-info-icon { + width: 8px; + height: 8px; + position: relative; + left: 29px; + } + + .more-info-icon::after { + width: 8px; + height: 8px; + line-height: 8px; + font-size: 8px; + } + + p { + width: 50px; + height: 10px; + left: 17px; + font-weight: 400; + font-size: 10.5px; + line-height: 10px; + } + + :host([deep-mode]) p { + width: 50px; + height: 10px; + position: relative; + left: 17px; + font-weight: 400; + font-size: 10.5px; + line-height: 10px; + } + + } + + + @media screen and (max-width: 1200px) { + .with-border { + border-radius: 16px; + } + + .icon-button::before { + width: 48px; + height: 48px; + line-height: 48px; + font-size: 48px; + } + + .icon-with-state::before { + position: relative; + left: 22px; + } + + .more-info-icon { + width: 16px; + height: 16px; + position: relative; + left: 58px; + } + + .more-info-icon::after { + width: 16px; + height: 16px; + line-height: 16px; + font-size: 16px; + } + + p { + width: 100px; + height: 20px; + left: 34px; + font-size: 21px; + line-height: 20px; + } + } + ` +} + +declare global { + interface HTMLElementTagNameMap { + 'icon-control-bar': IconControlBar + } +} diff --git a/src/components/icon-control-bar/index.ts b/src/components/icon-control-bar/index.ts new file mode 100644 index 0000000..3aab161 --- /dev/null +++ b/src/components/icon-control-bar/index.ts @@ -0,0 +1 @@ +export * from './icon-control-bar.js' diff --git a/src/components/icon-control-bar/interface.ts b/src/components/icon-control-bar/interface.ts new file mode 100644 index 0000000..37700c0 --- /dev/null +++ b/src/components/icon-control-bar/interface.ts @@ -0,0 +1,9 @@ +export interface WebActivity { + start(): Promise + cancel(): void +} + +export var WebActivity: { + prototype: WebActivity + new (name: string, data?: any): WebActivity +} diff --git a/src/components/icon-control-bar/package.json b/src/components/icon-control-bar/package.json new file mode 100644 index 0000000..b4688f7 --- /dev/null +++ b/src/components/icon-control-bar/package.json @@ -0,0 +1,22 @@ +{ + "name": "@star-web-components/icon-control-bar", + "version": "0.0.1", + "description": "", + "type": "module", + "main": "./index.js", + "module": "./index.js", + "exports": { + ".": { + "default": "./index.js" + }, + "./index": { + "default": "./index.js" + }, + "./icon-control-bar.js": { + "default": "./icon-control-bar.js" + }, + "./package.json": "./package.json" + }, + "author": "", + "license": "ISC" +} diff --git a/src/components/icon-control-bar/tsconfig.json b/src/components/icon-control-bar/tsconfig.json new file mode 100644 index 0000000..f77af19 --- /dev/null +++ b/src/components/icon-control-bar/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "composite": true, + "rootDir": "../../" + }, + "include": ["*.ts", "./interface.js"] +} diff --git a/src/index.ts b/src/index.ts index f05b2b7..8ee91f6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,8 +15,8 @@ import './components/toast/toast' import './components/picker/picker' import './components/overflowmenu/overflowmenu' import './components/slider/slider' -import './components/control-center/icon-item' -import './components/control-center/icons-one-line' +import './components/icon-control-bar/icon-control-bar' +import './components/icon-control-bar-group/icon-control-bar-group' import './components/prompt/prompt' import './components/digicipher/digicipher' import './components/pattern-view/pattern-view' diff --git a/src/test/panels/control-center/control-center.ts b/src/test/panels/control-center/control-center.ts index ca8ffb2..866bfde 100644 --- a/src/test/panels/control-center/control-center.ts +++ b/src/test/panels/control-center/control-center.ts @@ -1,101 +1,117 @@ -import {html, css, LitElement} from 'lit' +import {html, LitElement} from 'lit' import {customElement, query} from 'lit/decorators.js' -import {IconItem, IconType} from "../../../components/control-center/icon-item" -import "../../../components/control-center/icon-item" -import {IconsOneLineType} from "../../../components/control-center/icons-one-line" -import {UlType} from "../../../components/ul/ul" -import {HeaderBarType} from "../../../components/control-center/header-bar" -import "../../../components/control-center/icons-one-line" -import "../../../components/ul/ul" -import "../../../components/control-center/header-bar" -import "../../../components/control-center/pull-down-menu" -import "../../../components/control-center/control-center-bar" +import {IconControlBarType} from '../../../components/icon-control-bar/icon-control-bar' +import '../../../components/icon-control-bar/icon-control-bar' +import {IconControlBarGroupType} from '../../../components/icon-control-bar-group/icon-control-bar-group' +import {UlType} from '../../../components/ul/ul' +import {HeaderBarType} from '../../../components/header-bar/header-bar' +import '../../../components/icon-control-bar-group/icon-control-bar-group' +import '../../../components/ul/ul' +import '../../../components/header-bar/header-bar' @customElement('panel-control-center') export class PanelControlCenter extends LitElement { - @query('icon-item[icon="wifi-4"]') wifiIcon!: LitElement; - @query('icon-item[icon="crop"]') cropBtn!: LitElement; - @query('icon-item[icon="brightness"]') brightnessBtn!: LitElement; + @query('icon-control-bar[icon="wifi-4"]') wifiIcon!: LitElement + @query('icon-control-bar[icon="crop"]') cropBtn!: LitElement + @query('icon-control-bar[icon="brightness"]') brightnessBtn!: LitElement render() { return html` - -

带状态的图标,点击有背景色变化,绑定settingsObserver监测值

- -
-

基本图标

- -
-

基本图标,点击有背景色变化

- -
-

基本图标,不带边框

- -
+ +

带状态的图标,点击有背景色变化,绑定settingsObserver监测值

+ +
+

基本图标

+ +
+

基本图标,点击有背景色变化

+ +
+

基本图标,不带边框

+ +
- -

一行带状态的图标

- - - - - -
-
-

一个box框,框内是由短竖线分隔开的基本图标

- - - - - - -
-
+ +

一行带状态的图标

+ + + + + +
+
+

一个box框,框内是由短竖线分隔开的基本图标

+ + + + + + +
+
- - -

header带时间

- - - - -
-

header带时间/日期/星期

- - - -
-
- - - - - - - - - ` - - // return html` - // - // - // - // - - // ` - - // return html` - // - // - // ` - } - - static styles = css` - control-center-bar { - width: 1200px; - height: 1920px; - } - `; - handleEvent(event: Event) { - console.log("click on icon item: " + (event.target as IconItem).icon); + +

header带时间

+ + + + +
+

header带时间/日期/星期

+ + + +
+
+ ` } } diff --git a/src/test/panels/root.ts b/src/test/panels/root.ts index 5fcb9c6..53204b3 100644 --- a/src/test/panels/root.ts +++ b/src/test/panels/root.ts @@ -119,9 +119,6 @@ export class PanelRoot extends LitElement {
>>>>>> 45627df8470c7bd87bfd6e38897cf3b896b0234d icon="scene" iconcolor="#EB7347" href="#slider"