细分组件
This commit is contained in:
parent
9191e09646
commit
861ad2a586
|
@ -1,9 +0,0 @@
|
||||||
interface WebActivity {
|
|
||||||
start(): Promise<any>;
|
|
||||||
cancel(): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare var WebActivity: {
|
|
||||||
prototype: WebActivity;
|
|
||||||
new(name: string, data?: any): WebActivity;
|
|
||||||
};
|
|
|
@ -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`
|
||||||
|
<div
|
||||||
|
class="sliderBar"
|
||||||
|
data-icon="brightness"
|
||||||
|
value=${this.value}
|
||||||
|
max=${this.max}
|
||||||
|
@touchstart=${this}
|
||||||
|
@touchmove=${this}
|
||||||
|
@touchend=${this}
|
||||||
|
>
|
||||||
|
<div class="progress"></div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './brightness-slider.js'
|
|
@ -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"
|
||||||
|
}
|
|
@ -4,5 +4,5 @@
|
||||||
"composite": true,
|
"composite": true,
|
||||||
"rootDir": "../../"
|
"rootDir": "../../"
|
||||||
},
|
},
|
||||||
"include": ["../../../global.d.ts", "*.ts"]
|
"include": ["*.ts"]
|
||||||
}
|
}
|
|
@ -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
|
|
||||||
<icon-item type=${IconType.WITH_STATE} icon="wifi-4" bgchange=true settingsKey="wifi.enabled" stateDesc=""></icon-item>
|
|
||||||
|
|
||||||
<icon-item type=${IconType.BASE} icon="crop"></icon-item>
|
|
||||||
|
|
||||||
<icon-item type=${IconType.BASE} icon="brightness" bgchange=true settingsKey="screen.automatic-brightness"></icon-item>
|
|
||||||
|
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="settings"></icon-item>
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
# icons-online
|
|
||||||
对`icon-item`的进一步组合、封装。
|
|
||||||
分为两类:
|
|
||||||
`IconsOneLineType.BASE`类型:
|
|
||||||
需传入`count`,为所插入插槽元素的个数,默认数值为4;
|
|
||||||
需插入插槽元素,显示为一个box框,框内是由短竖线分隔开的基本图标。
|
|
||||||
`IconsOneLineType.WITH_STATE`类型:
|
|
||||||
需传入`count`,为所插入插槽元素的个数,默认数值为2;
|
|
||||||
需插入插槽元素,显示为一行带状态的图标。
|
|
||||||
|
|
||||||
示例:
|
|
||||||
```html
|
|
||||||
<icons-one-line type=${IconsOneLineType.WITH_STATE}>
|
|
||||||
<icon-item type=${IconType.WITH_STATE} icon="wifi-4" isActive=true settingsKey="wifi.enabled" stateDesc=""></icon-item>
|
|
||||||
<icon-item type=${IconType.WITH_STATE} icon="bluetooth" isActive=true settingsKey="bluetooth.enabled"></icon-item>
|
|
||||||
</icons-one-line>
|
|
||||||
|
|
||||||
|
|
||||||
<icons-one-line type=${IconsOneLineType.BASE} count=3>
|
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="crop"></icon-item>
|
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="video"></icon-item>
|
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="camera"></icon-item>
|
|
||||||
</icons-one-line>
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
# header-bar
|
|
||||||
用于显示下拉控件栏、下拉通知栏最顶部的header。
|
|
||||||
分为两类:
|
|
||||||
`HeaderBarType.ONLY_TIME`类型:
|
|
||||||
header中显示时间和任意图标,需插入插槽元素
|
|
||||||
`HeaderBarType.DATE_TIME`类型:
|
|
||||||
header中显示日期、星期、时间和任意图标,需插入插槽元素
|
|
||||||
示例:
|
|
||||||
```html
|
|
||||||
<header-bar type=${HeaderBarType.ONLY_TIME}>
|
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="compose"></icon-item>
|
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="settings"></icon-item>
|
|
||||||
</header-bar>
|
|
||||||
|
|
||||||
|
|
||||||
<header-bar type=${HeaderBarType.DATE_TIME}>
|
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="settings"></icon-item>
|
|
||||||
</header-bar>
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
# control-center
|
|
||||||
下拉控件栏组件。
|
|
||||||
包括`header-bar`和中间控件部分。中间控件部分由slot元素插入。
|
|
||||||
|
|
||||||
```html
|
|
||||||
<control-center>
|
|
||||||
<div class="brightness"></div>
|
|
||||||
<icon-item type=${IconType.BASE} icon="brightness"></icon-item>
|
|
||||||
</control-center>
|
|
||||||
```
|
|
||||||
|
|
||||||
# control-center-bar
|
|
||||||
`control-center`实例
|
|
||||||
|
|
||||||
说明: 因现有下拉栏顶部的状态栏是采用`background-image:-moz-element(#statusbar-icons)`方式获取,所以使用`slot`获取。
|
|
||||||
```html
|
|
||||||
<control-center-bar>
|
|
||||||
<div slot="status-bar"></div>
|
|
||||||
</control-center-bar>
|
|
||||||
```
|
|
|
@ -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`
|
|
||||||
<slot name="status-bar"></slot>
|
|
||||||
<pull-down-menu type=${PullDownMenuType.HEADER_WITH_TIME}>
|
|
||||||
<icons-one-line type=${IconsOneLineType.WITH_STATE}>
|
|
||||||
<icon-item type=${IconType.WITH_STATE} id="wifi" icon="wifi-4" bgchange=true settingsKey="wifi.enabled" stateDesc=""></icon-item>
|
|
||||||
<icon-item type=${IconType.WITH_STATE} id="bluetooth" icon="bluetooth" bgchange=true settingsKey="bluetooth.enabled"></icon-item>
|
|
||||||
</icons-one-line>
|
|
||||||
<div class="icon-section">
|
|
||||||
<gaia-container id="icon-only"></gaia-container>
|
|
||||||
</div>
|
|
||||||
<div class="brightness">
|
|
||||||
<light-slider id="screen-brightness"></light-slider>
|
|
||||||
<icon-item type=${IconType.BASE} icon="brightness" bgchange=true settingsKey="screen.automatic-brightness"></icon-item>
|
|
||||||
</div>
|
|
||||||
<icons-one-line type=${IconsOneLineType.BASE}>
|
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="crop"></icon-item>
|
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="video"></icon-item>
|
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="camera"></icon-item>
|
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="o"></icon-item>
|
|
||||||
</icons-one-line>
|
|
||||||
<div class="button-wrapper">
|
|
||||||
<div id="toggle-button"></div>
|
|
||||||
</div>
|
|
||||||
<div class="media-player"></div>
|
|
||||||
<gaia-dialog-list id="wifi-list" hidden>
|
|
||||||
<h1>WLAN</h1>
|
|
||||||
<h2>可用WLAN列表</h2>
|
|
||||||
</gaia-dialog-list>
|
|
||||||
<gaia-dialog-list id="bluetooth-list" hidden>
|
|
||||||
<h1>蓝牙</h1>
|
|
||||||
<h2>已配对的设备</h2>
|
|
||||||
</gaia-dialog-list>
|
|
||||||
</pull-down-menu>
|
|
||||||
`
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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)";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 = `
|
|
||||||
<slot></slot>
|
|
||||||
<style>${this.shadowStyle}</style>
|
|
||||||
`
|
|
||||||
}
|
|
||||||
|
|
||||||
customElements.define("gaia-container", GaiaContainer);
|
|
|
@ -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`
|
|
||||||
<div class="time-outer">
|
|
||||||
<div id="time"></div>
|
|
||||||
<div class="time-icons">
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
getTimeAndDate(): HTMLTemplateResult {
|
|
||||||
return html`
|
|
||||||
<div class="time-date-outer">
|
|
||||||
<div class="time-date">
|
|
||||||
<div id="time"></div>
|
|
||||||
<div id="date"></div>
|
|
||||||
</div>
|
|
||||||
<div class="time-date-icons">
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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`
|
|
||||||
<style>
|
|
||||||
:host {
|
|
||||||
width: 104px;
|
|
||||||
height: 104px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
`;
|
|
||||||
|
|
||||||
return html `
|
|
||||||
<div class="icon-button icon-base with-border" data-icon=${this.icon} @click=${this.handleClick} @touchstart=${this.handlePress} @touchend=${this.handlePressEnd}>
|
|
||||||
${iconstyle}
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
getbaseWithOutBorder(): HTMLTemplateResult | typeof nothing {
|
|
||||||
if (!this.icon) {
|
|
||||||
console.error('【icon-item】缺少 icon 参数');
|
|
||||||
return nothing;
|
|
||||||
}
|
|
||||||
|
|
||||||
return html `
|
|
||||||
<div class="icon-button icon-base without-border" data-icon=${this.icon} @click=${this.handleClick} @touchstart=${this.handlePress} @touchend=${this.handlePressEnd}>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
getwithstate(): HTMLTemplateResult | typeof nothing {
|
|
||||||
if (!this.icon) {
|
|
||||||
console.error('【icon-item】缺少 icon 参数');
|
|
||||||
return nothing;
|
|
||||||
}
|
|
||||||
|
|
||||||
const iconstyle = html`
|
|
||||||
<style>
|
|
||||||
:host {
|
|
||||||
width: 240px;
|
|
||||||
height: 108px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
`;
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<div class="icon-button icon-with-state with-border config-activity" data-icon=${this.icon} @click=${this.handleClick} @touchstart=${this.handlePress} @touchend=${this.handlePressEnd}>
|
|
||||||
<p>${this.stateDesc}</p>
|
|
||||||
<div class="more-info-icon" @click=${this.handleInfo} data-icon="expand-left"></div>
|
|
||||||
${iconstyle}
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
@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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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`
|
|
||||||
<style>
|
|
||||||
.icon-only > div > ::slotted(*) {
|
|
||||||
width: calc(100% / ${this.count}) !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
`
|
|
||||||
: nothing;
|
|
||||||
return html`
|
|
||||||
<div class="icon-only">
|
|
||||||
<div>
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
${colorstyle}
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
getIconWithState(): HTMLTemplateResult {
|
|
||||||
return html`
|
|
||||||
<div class="icon-with-state">
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export * from './control-center-bar.js'
|
|
|
@ -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`
|
|
||||||
<div class="sliderBar" data-icon="brightness" value=${this.value} max=${this.max} @touchstart=${this} @touchmove=${this} @touchend=${this}>
|
|
||||||
<div class="progress"></div>
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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"
|
|
||||||
}
|
|
|
@ -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`
|
|
||||||
<div class="inner">
|
|
||||||
<header-bar type=${HeaderBarType.ONLY_TIME}>
|
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="compose" @click=${this}></icon-item>
|
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="settings" @click=${this}></icon-item>
|
|
||||||
</header-bar>
|
|
||||||
<div class="all-quick-icons">
|
|
||||||
<slot @slotchange=${this}></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
}
|
|
||||||
|
|
||||||
getTimeAndDate(): HTMLTemplateResult {
|
|
||||||
return html`
|
|
||||||
<div class="inner">
|
|
||||||
<header-bar type=${HeaderBarType.DATE_TIME}>
|
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="settings" @click=${this}></icon-item>
|
|
||||||
</header-bar>
|
|
||||||
<div class="others">
|
|
||||||
<slot @slotchange=${this}></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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`
|
||||||
|
<div class="inner">
|
||||||
|
<header-bar type=${HeaderBarType.ONLY_TIME}>
|
||||||
|
<icon-control-bar
|
||||||
|
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||||
|
icon="compose"
|
||||||
|
@click=${this}
|
||||||
|
></icon-control-bar>
|
||||||
|
<icon-control-bar
|
||||||
|
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||||
|
icon="settings"
|
||||||
|
@click=${this}
|
||||||
|
></icon-control-bar>
|
||||||
|
</header-bar>
|
||||||
|
<div class="all-quick-icons">
|
||||||
|
<slot @slotchange=${this}></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
getTimeAndDate(): HTMLTemplateResult {
|
||||||
|
return html`
|
||||||
|
<div class="inner">
|
||||||
|
<header-bar type=${HeaderBarType.DATE_TIME}>
|
||||||
|
<icon-control-bar
|
||||||
|
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||||
|
icon="settings"
|
||||||
|
@click=${this}
|
||||||
|
></icon-control-bar>
|
||||||
|
</header-bar>
|
||||||
|
<div class="others">
|
||||||
|
<slot @slotchange=${this}></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './drop-down-menu.js'
|
|
@ -0,0 +1,9 @@
|
||||||
|
export interface WebActivity {
|
||||||
|
start(): Promise<any>
|
||||||
|
cancel(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
export var WebActivity: {
|
||||||
|
prototype: WebActivity
|
||||||
|
new (name: string, data?: any): WebActivity
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
|
@ -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"
|
||||||
|
]
|
||||||
|
}
|
|
@ -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`
|
||||||
|
<div class="time-outer">
|
||||||
|
<div id="time"></div>
|
||||||
|
<div class="time-icons">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
getTimeAndDate(): HTMLTemplateResult {
|
||||||
|
return html`
|
||||||
|
<div class="time-date-outer">
|
||||||
|
<div class="time-date">
|
||||||
|
<div id="time"></div>
|
||||||
|
<div id="date"></div>
|
||||||
|
</div>
|
||||||
|
<div class="time-date-icons">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './header-bar.js'
|
|
@ -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"
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"rootDir": "../../"
|
||||||
|
},
|
||||||
|
"include": ["*.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`
|
||||||
|
<style>
|
||||||
|
.icon-only > div > ::slotted(*) {
|
||||||
|
width: calc(100% / ${this.count}) !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
`
|
||||||
|
: nothing
|
||||||
|
return html`
|
||||||
|
<div class="icon-only">
|
||||||
|
<div>
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
${colorstyle}
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
getIconWithState(): HTMLTemplateResult {
|
||||||
|
return html`
|
||||||
|
<div class="icon-with-state">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './icon-control-bar-group.js'
|
|
@ -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"
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"rootDir": "../../"
|
||||||
|
},
|
||||||
|
"include": ["*.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`
|
||||||
|
<style>
|
||||||
|
@media screen and (max-width: 1200px) {
|
||||||
|
:host {
|
||||||
|
width: 104px;
|
||||||
|
height: 104px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
:host {
|
||||||
|
width: 52px;
|
||||||
|
height: 52px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
`
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<div
|
||||||
|
class="icon-button icon-base with-border"
|
||||||
|
data-icon=${this.icon}
|
||||||
|
@click=${this.handleClick}
|
||||||
|
@touchstart=${this.handlePress}
|
||||||
|
@touchend=${this.handlePressEnd}
|
||||||
|
>
|
||||||
|
${iconstyle}
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
getbaseWithOutBorder(): HTMLTemplateResult | typeof nothing {
|
||||||
|
if (!this.icon) {
|
||||||
|
console.error('【icon-control-bar】缺少 icon 参数')
|
||||||
|
return nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<div
|
||||||
|
class="icon-button icon-base without-border"
|
||||||
|
data-icon=${this.icon}
|
||||||
|
@click=${this.handleClick}
|
||||||
|
@touchstart=${this.handlePress}
|
||||||
|
@touchend=${this.handlePressEnd}
|
||||||
|
></div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
getwithstate(): HTMLTemplateResult | typeof nothing {
|
||||||
|
if (!this.icon) {
|
||||||
|
console.error('【icon-control-bar】缺少 icon 参数')
|
||||||
|
return nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
const iconstyle = html`
|
||||||
|
<style>
|
||||||
|
@media screen and (max-width: 1200px) {
|
||||||
|
:host {
|
||||||
|
width: 240px;
|
||||||
|
height: 108px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
:host {
|
||||||
|
width: 120px;
|
||||||
|
height: 54px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
`
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<div
|
||||||
|
class="icon-button icon-with-state with-border config-activity"
|
||||||
|
data-icon=${this.icon}
|
||||||
|
@click=${this.handleClick}
|
||||||
|
@touchstart=${this.handlePress}
|
||||||
|
@touchend=${this.handlePressEnd}
|
||||||
|
>
|
||||||
|
<p>${this.stateDesc}</p>
|
||||||
|
<div
|
||||||
|
class="more-info-icon"
|
||||||
|
@click=${this.handleInfo}
|
||||||
|
data-icon="expand-left"
|
||||||
|
></div>
|
||||||
|
${iconstyle}
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
@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
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './icon-control-bar.js'
|
|
@ -0,0 +1,9 @@
|
||||||
|
export interface WebActivity {
|
||||||
|
start(): Promise<any>
|
||||||
|
cancel(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
export var WebActivity: {
|
||||||
|
prototype: WebActivity
|
||||||
|
new (name: string, data?: any): WebActivity
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"rootDir": "../../"
|
||||||
|
},
|
||||||
|
"include": ["*.ts", "./interface.js"]
|
||||||
|
}
|
|
@ -15,8 +15,8 @@ import './components/toast/toast'
|
||||||
import './components/picker/picker'
|
import './components/picker/picker'
|
||||||
import './components/overflowmenu/overflowmenu'
|
import './components/overflowmenu/overflowmenu'
|
||||||
import './components/slider/slider'
|
import './components/slider/slider'
|
||||||
import './components/control-center/icon-item'
|
import './components/icon-control-bar/icon-control-bar'
|
||||||
import './components/control-center/icons-one-line'
|
import './components/icon-control-bar-group/icon-control-bar-group'
|
||||||
import './components/prompt/prompt'
|
import './components/prompt/prompt'
|
||||||
import './components/digicipher/digicipher'
|
import './components/digicipher/digicipher'
|
||||||
import './components/pattern-view/pattern-view'
|
import './components/pattern-view/pattern-view'
|
||||||
|
|
|
@ -1,101 +1,117 @@
|
||||||
import {html, css, LitElement} from 'lit'
|
import {html, LitElement} from 'lit'
|
||||||
import {customElement, query} from 'lit/decorators.js'
|
import {customElement, query} from 'lit/decorators.js'
|
||||||
import {IconItem, IconType} from "../../../components/control-center/icon-item"
|
import {IconControlBarType} from '../../../components/icon-control-bar/icon-control-bar'
|
||||||
import "../../../components/control-center/icon-item"
|
import '../../../components/icon-control-bar/icon-control-bar'
|
||||||
import {IconsOneLineType} from "../../../components/control-center/icons-one-line"
|
import {IconControlBarGroupType} from '../../../components/icon-control-bar-group/icon-control-bar-group'
|
||||||
import {UlType} from "../../../components/ul/ul"
|
import {UlType} from '../../../components/ul/ul'
|
||||||
import {HeaderBarType} from "../../../components/control-center/header-bar"
|
import {HeaderBarType} from '../../../components/header-bar/header-bar'
|
||||||
import "../../../components/control-center/icons-one-line"
|
import '../../../components/icon-control-bar-group/icon-control-bar-group'
|
||||||
import "../../../components/ul/ul"
|
import '../../../components/ul/ul'
|
||||||
import "../../../components/control-center/header-bar"
|
import '../../../components/header-bar/header-bar'
|
||||||
import "../../../components/control-center/pull-down-menu"
|
|
||||||
import "../../../components/control-center/control-center-bar"
|
|
||||||
@customElement('panel-control-center')
|
@customElement('panel-control-center')
|
||||||
export class PanelControlCenter extends LitElement {
|
export class PanelControlCenter extends LitElement {
|
||||||
@query('icon-item[icon="wifi-4"]') wifiIcon!: LitElement;
|
@query('icon-control-bar[icon="wifi-4"]') wifiIcon!: LitElement
|
||||||
@query('icon-item[icon="crop"]') cropBtn!: LitElement;
|
@query('icon-control-bar[icon="crop"]') cropBtn!: LitElement
|
||||||
@query('icon-item[icon="brightness"]') brightnessBtn!: LitElement;
|
@query('icon-control-bar[icon="brightness"]') brightnessBtn!: LitElement
|
||||||
render() {
|
render() {
|
||||||
return html`
|
return html`
|
||||||
<star-ul type=${UlType.ONLY_HEADER} title="icon-item">
|
<star-ul type=${UlType.ONLY_HEADER} title="icon-control-bar">
|
||||||
<p>带状态的图标,点击有背景色变化,绑定settingsObserver监测值</p>
|
<p>带状态的图标,点击有背景色变化,绑定settingsObserver监测值</p>
|
||||||
<icon-item type=${IconType.WITH_STATE} icon="wifi-4" bgchange=true settingsKey="wifi.enabled" stateDesc="fgfgfhhhh" @click=${this}></icon-item>
|
<icon-control-bar
|
||||||
<br/>
|
type=${IconControlBarType.WITH_STATE}
|
||||||
<p>基本图标</p>
|
icon="wifi-4"
|
||||||
<icon-item type=${IconType.BASE} icon="crop" @click=${this}></icon-item>
|
bgchange="true"
|
||||||
<br/>
|
settingsKey="wifi.enabled"
|
||||||
<p>基本图标,点击有背景色变化</p>
|
stateDesc="fgfgfhhhh"
|
||||||
<icon-item type=${IconType.BASE} icon="brightness" bgchange=true settingsKey="screen.automatic-brightness" @click=${this}></icon-item>
|
@click=${this}
|
||||||
<br/>
|
></icon-control-bar>
|
||||||
<p>基本图标,不带边框</p>
|
<br />
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="settings"></icon-item>
|
<p>基本图标</p>
|
||||||
</star-ul>
|
<icon-control-bar type=${IconControlBarType.BASE} icon="crop" @click=${this}></icon-control-bar>
|
||||||
|
<br />
|
||||||
|
<p>基本图标,点击有背景色变化</p>
|
||||||
|
<icon-control-bar
|
||||||
|
type=${IconControlBarType.BASE}
|
||||||
|
icon="brightness"
|
||||||
|
bgchange="true"
|
||||||
|
settingsKey="screen.automatic-brightness"
|
||||||
|
@click=${this}
|
||||||
|
></icon-control-bar>
|
||||||
|
<br />
|
||||||
|
<p>基本图标,不带边框</p>
|
||||||
|
<icon-control-bar
|
||||||
|
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||||
|
icon="settings"
|
||||||
|
></icon-control-bar>
|
||||||
|
</star-ul>
|
||||||
|
|
||||||
<star-ul type=${UlType.ONLY_HEADER} title="icons-one-line">
|
<star-ul type=${UlType.ONLY_HEADER} title="icon-control-bar-group">
|
||||||
<p>一行带状态的图标</p>
|
<p>一行带状态的图标</p>
|
||||||
<icons-one-line type=${IconsOneLineType.WITH_STATE}>
|
<icon-control-bar-group type=${IconControlBarGroupType.WITH_STATE}>
|
||||||
<icon-item type=${IconType.WITH_STATE} icon="wifi-4" bgchange=true settingsKey="wifi.enabled" stateDesc=""></icon-item>
|
<icon-control-bar
|
||||||
<icon-item type=${IconType.WITH_STATE} icon="bluetooth" bgchange=true settingsKey="bluetooth.enabled"></icon-item>
|
type=${IconControlBarType.WITH_STATE}
|
||||||
<icon-item type=${IconType.WITH_STATE} icon="data" bgchange=true settingsKey="a.enabled"></icon-item>
|
icon="wifi-4"
|
||||||
</icons-one-line>
|
bgchange="true"
|
||||||
<br/>
|
settingsKey="wifi.enabled"
|
||||||
<br/>
|
stateDesc=""
|
||||||
<p>一个box框,框内是由短竖线分隔开的基本图标</p>
|
></icon-control-bar>
|
||||||
<icons-one-line type=${IconsOneLineType.BASE} count=4>
|
<icon-control-bar
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="crop"></icon-item>
|
type=${IconControlBarType.WITH_STATE}
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="video"></icon-item>
|
icon="bluetooth"
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="camera"></icon-item>
|
bgchange="true"
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="o"></icon-item>
|
settingsKey="bluetooth.enabled"
|
||||||
</icons-one-line>
|
></icon-control-bar>
|
||||||
<br/>
|
<icon-control-bar
|
||||||
</star-ul>
|
type=${IconControlBarType.WITH_STATE}
|
||||||
|
icon="data"
|
||||||
|
bgchange="true"
|
||||||
|
settingsKey="a.enabled"
|
||||||
|
></icon-control-bar>
|
||||||
|
</icon-control-bar-group>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<p>一个box框,框内是由短竖线分隔开的基本图标</p>
|
||||||
|
<icon-control-bar-group type=${IconControlBarGroupType.BASE} count="4">
|
||||||
|
<icon-control-bar
|
||||||
|
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||||
|
icon="crop"
|
||||||
|
></icon-control-bar>
|
||||||
|
<icon-control-bar
|
||||||
|
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||||
|
icon="video"
|
||||||
|
></icon-control-bar>
|
||||||
|
<icon-control-bar
|
||||||
|
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||||
|
icon="camera"
|
||||||
|
></icon-control-bar>
|
||||||
|
<icon-control-bar type=${IconControlBarType.BASE_WITHOUT_BORDER} icon="o"></icon-control-bar>
|
||||||
|
</icon-control-bar-group>
|
||||||
|
<br />
|
||||||
|
</star-ul>
|
||||||
|
|
||||||
|
<star-ul type=${UlType.ONLY_HEADER} title="header-bar">
|
||||||
<star-ul type=${UlType.ONLY_HEADER} title="header-bar">
|
<p>header带时间</p>
|
||||||
<p>header带时间</p>
|
<header-bar type=${HeaderBarType.ONLY_TIME}>
|
||||||
<header-bar type=${HeaderBarType.ONLY_TIME}>
|
<icon-control-bar
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="compose"></icon-item>
|
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="settings"></icon-item>
|
icon="compose"
|
||||||
</header-bar>
|
></icon-control-bar>
|
||||||
<br/>
|
<icon-control-bar
|
||||||
<p>header带时间/日期/星期</p>
|
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||||
<header-bar type=${HeaderBarType.DATE_TIME}>
|
icon="settings"
|
||||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="settings"></icon-item>
|
></icon-control-bar>
|
||||||
</header-bar>
|
</header-bar>
|
||||||
<br/>
|
<br />
|
||||||
</star-ul>
|
<p>header带时间/日期/星期</p>
|
||||||
|
<header-bar type=${HeaderBarType.DATE_TIME}>
|
||||||
|
<icon-control-bar
|
||||||
<star-ul type=${UlType.ONLY_HEADER} title="control-center">
|
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||||
<control-center>
|
icon="settings"
|
||||||
<panel-icon></panel-icon>
|
></icon-control-bar>
|
||||||
<icon-item type=${IconType.BASE} icon="brightness"></icon-item>
|
</header-bar>
|
||||||
</control-center>
|
<br />
|
||||||
</star-ul>
|
</star-ul>
|
||||||
`
|
`
|
||||||
|
|
||||||
// return html`
|
|
||||||
// <control-center>
|
|
||||||
// <panel-icon></panel-icon>
|
|
||||||
// <icon-item type=${IconType.BASE} icon="brightness"></icon-item>
|
|
||||||
// </control-center>
|
|
||||||
|
|
||||||
// `
|
|
||||||
|
|
||||||
// return html`
|
|
||||||
// <control-center-bar>
|
|
||||||
// </control-center-bar>
|
|
||||||
// `
|
|
||||||
}
|
|
||||||
|
|
||||||
static styles = css`
|
|
||||||
control-center-bar {
|
|
||||||
width: 1200px;
|
|
||||||
height: 1920px;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
handleEvent(event: Event) {
|
|
||||||
console.log("click on icon item: " + (event.target as IconItem).icon);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,9 +119,6 @@ export class PanelRoot extends LitElement {
|
||||||
<hr />
|
<hr />
|
||||||
<star-li
|
<star-li
|
||||||
type=${LiType.ICON_LABEL}
|
type=${LiType.ICON_LABEL}
|
||||||
<<<<<<< HEAD
|
|
||||||
label="SliderTest"
|
|
||||||
=======
|
|
||||||
label="开关"
|
label="开关"
|
||||||
icon="switch"
|
icon="switch"
|
||||||
iconcolor="#EB7347"
|
iconcolor="#EB7347"
|
||||||
|
@ -131,7 +128,6 @@ export class PanelRoot extends LitElement {
|
||||||
<star-li
|
<star-li
|
||||||
type=${LiType.ICON_LABEL}
|
type=${LiType.ICON_LABEL}
|
||||||
label="滑动条"
|
label="滑动条"
|
||||||
>>>>>>> 45627df8470c7bd87bfd6e38897cf3b896b0234d
|
|
||||||
icon="scene"
|
icon="scene"
|
||||||
iconcolor="#EB7347"
|
iconcolor="#EB7347"
|
||||||
href="#slider"
|
href="#slider"
|
||||||
|
|
Loading…
Reference in New Issue