|
| 1 | +/** |
| 2 | + * 个性磁铁小部件 |
| 3 | + */ |
| 4 | + |
| 5 | +import {isLaunchInsideApp, showActionSheet, showNotification, showPreviewOptions} from '@app/lib/help' |
| 6 | +import {Col} from '@app/lib/components' |
| 7 | +import {WstackProps} from '@app/types/widget' |
| 8 | +import {FC} from 'react' |
| 9 | + |
| 10 | +// 文字颜色 |
| 11 | +const textColor = '#ffffff' |
| 12 | + |
| 13 | +// 好看的颜色 |
| 14 | +const colors = { |
| 15 | + red: '#e54d42', |
| 16 | + orange: '#f37b1d', |
| 17 | + yellow: '#fbbd08', |
| 18 | + olive: '#8dc63f', |
| 19 | + green: '#39b54a', |
| 20 | + cyan: '#1cbbb4', |
| 21 | + blue: '#0081ff', |
| 22 | + purple: '#6739b6', |
| 23 | + mauve: '#9c26b0', |
| 24 | + pink: '#e03997', |
| 25 | + brown: '#a5673f', |
| 26 | + grey: '#8799a3', |
| 27 | + black: '#000000', |
| 28 | +} |
| 29 | + |
| 30 | +/**格子组件参数*/ |
| 31 | +interface GridProps { |
| 32 | + /** icon 名字*/ |
| 33 | + iconName?: string |
| 34 | + |
| 35 | + /**格子背景*/ |
| 36 | + background?: WstackProps['background'] |
| 37 | + |
| 38 | + /**文字*/ |
| 39 | + text?: string |
| 40 | + |
| 41 | + /**点击格子跳转的链接*/ |
| 42 | + href?: string |
| 43 | +} |
| 44 | + |
| 45 | +/**格子组件*/ |
| 46 | +const Grid: FC<GridProps> = ({...props}) => { |
| 47 | + const {iconName, background, text, href} = props |
| 48 | + const bgColors: string[] = Object.values(colors) |
| 49 | + const bgRandom = Math.floor(Math.random() * bgColors.length) |
| 50 | + const bgColor = bgColors[bgRandom] |
| 51 | + return ( |
| 52 | + <wstack background={background || bgColor} href={href} borderColor="#00000088" borderWidth={1}> |
| 53 | + <Col |
| 54 | + background={/^\#[\d]+$/.test(String(background)) ? '#00000000' : '#00000033'} |
| 55 | + alignItems="center" |
| 56 | + justifyContent="center" |
| 57 | + > |
| 58 | + {iconName && <wimage src={iconName} filter={textColor} width={20} height={20}></wimage>} |
| 59 | + <wspacer length={10}></wspacer> |
| 60 | + {(!iconName || text) && ( |
| 61 | + <wtext font={new Font('heavymenlo', 12.5)} textColor={textColor}> |
| 62 | + {text || ''} |
| 63 | + </wtext> |
| 64 | + )} |
| 65 | + </Col> |
| 66 | + </wstack> |
| 67 | + ) |
| 68 | +} |
| 69 | + |
| 70 | +class Launcher { |
| 71 | + private config: GridProps[] |
| 72 | + constructor(config: GridProps[]) { |
| 73 | + this.config = config |
| 74 | + } |
| 75 | + async init() { |
| 76 | + if (isLaunchInsideApp()) { |
| 77 | + return await this.showMenu() |
| 78 | + } |
| 79 | + const widget = (await this.render()) as ListWidget |
| 80 | + Script.setWidget(widget) |
| 81 | + Script.complete() |
| 82 | + } |
| 83 | + |
| 84 | + //渲染组件 |
| 85 | + async render(): Promise<unknown> { |
| 86 | + if (isLaunchInsideApp()) { |
| 87 | + await showNotification({title: '稍等片刻', body: '小部件渲染中...', sound: 'alert'}) |
| 88 | + } |
| 89 | + // 多久(毫秒)更新一次小部件(默认24小时) |
| 90 | + const updateInterval = 24 * 60 * 60 * 1000 |
| 91 | + // 渲染尺寸 |
| 92 | + const size = config.widgetFamily |
| 93 | + return ( |
| 94 | + <wbox |
| 95 | + padding={[0, 0, 0, 0]} |
| 96 | + updateDate={new Date(Date.now() + updateInterval)} |
| 97 | + href={size === 'small' ? this.config[0].href : ''} |
| 98 | + > |
| 99 | + {size === 'small' && this.renderSmall()} |
| 100 | + {size === 'medium' && this.renderMedium()} |
| 101 | + {size === 'large' && this.renderLarge()} |
| 102 | + </wbox> |
| 103 | + ) |
| 104 | + } |
| 105 | + |
| 106 | + // 渲染小尺寸 |
| 107 | + renderSmall() { |
| 108 | + return ( |
| 109 | + <wstack flexDirection="column"> |
| 110 | + <wstack> |
| 111 | + <Grid {...this.config[0]}></Grid> |
| 112 | + </wstack> |
| 113 | + </wstack> |
| 114 | + ) |
| 115 | + } |
| 116 | + |
| 117 | + // 渲染中尺寸 |
| 118 | + renderMedium() { |
| 119 | + return ( |
| 120 | + <wstack> |
| 121 | + <Grid {...this.config[0]}></Grid> |
| 122 | + <wstack flexDirection="column"> |
| 123 | + <wstack> |
| 124 | + <Grid {...this.config[1]}></Grid> |
| 125 | + <Grid {...this.config[2]}></Grid> |
| 126 | + </wstack> |
| 127 | + <wstack> |
| 128 | + <Grid {...this.config[3]}></Grid> |
| 129 | + <Grid {...this.config[4]}></Grid> |
| 130 | + </wstack> |
| 131 | + </wstack> |
| 132 | + </wstack> |
| 133 | + ) |
| 134 | + } |
| 135 | + |
| 136 | + // 渲染大尺寸 |
| 137 | + renderLarge() { |
| 138 | + return ( |
| 139 | + <wstack flexDirection="column"> |
| 140 | + {/* 上半部分 */} |
| 141 | + <wstack> |
| 142 | + <Grid {...this.config[0]}></Grid> |
| 143 | + <wstack flexDirection="column"> |
| 144 | + <wstack> |
| 145 | + <Grid {...this.config[1]}></Grid> |
| 146 | + <Grid {...this.config[2]}></Grid> |
| 147 | + </wstack> |
| 148 | + <wstack> |
| 149 | + <Grid {...this.config[3]}></Grid> |
| 150 | + <Grid {...this.config[4]}></Grid> |
| 151 | + </wstack> |
| 152 | + </wstack> |
| 153 | + </wstack> |
| 154 | + {/* 下半部分 */} |
| 155 | + <wstack> |
| 156 | + <wstack flexDirection="column"> |
| 157 | + <wstack> |
| 158 | + <Grid {...this.config[5]}></Grid> |
| 159 | + <Grid {...this.config[6]}></Grid> |
| 160 | + </wstack> |
| 161 | + <Grid {...this.config[7]}></Grid> |
| 162 | + </wstack> |
| 163 | + <wstack flexDirection="column"> |
| 164 | + <Grid {...this.config[8]}></Grid> |
| 165 | + <wstack> |
| 166 | + <Grid {...this.config[9]}></Grid> |
| 167 | + <Grid {...this.config[10]}></Grid> |
| 168 | + </wstack> |
| 169 | + </wstack> |
| 170 | + </wstack> |
| 171 | + </wstack> |
| 172 | + ) |
| 173 | + } |
| 174 | + |
| 175 | + // 显示菜单 |
| 176 | + async showMenu() { |
| 177 | + const selectIndex = await showActionSheet({ |
| 178 | + title: '菜单', |
| 179 | + itemList: ['预览组件'], |
| 180 | + }) |
| 181 | + switch (selectIndex) { |
| 182 | + case 0: |
| 183 | + await showPreviewOptions(this.render.bind(this)) |
| 184 | + break |
| 185 | + } |
| 186 | + } |
| 187 | +} |
| 188 | + |
| 189 | +const luancherConfig: GridProps[] = [ |
| 190 | + { |
| 191 | + href: 'weixin://scanqrcode', |
| 192 | + background: colors.green, |
| 193 | + iconName: 'barcode.viewfinder', |
| 194 | + text: '扫一扫', |
| 195 | + }, |
| 196 | + { |
| 197 | + href: 'alipayqr://platformapi/startapp?saId=10000007', |
| 198 | + background: colors.blue, |
| 199 | + iconName: 'barcode.viewfinder', |
| 200 | + text: '扫一扫', |
| 201 | + }, |
| 202 | + { |
| 203 | + href: 'weixin://', |
| 204 | + background: colors.green, |
| 205 | + iconName: 'message.fill', |
| 206 | + text: '微信', |
| 207 | + }, |
| 208 | + { |
| 209 | + href: 'orpheuswidget://', |
| 210 | + background: colors.red, |
| 211 | + iconName: 'music.note', |
| 212 | + text: '网易云', |
| 213 | + }, |
| 214 | + { |
| 215 | + href: 'alipay://platformapi/startapp?appId=20000056', |
| 216 | + background: colors.blue, |
| 217 | + iconName: 'qrcode', |
| 218 | + text: '付款码', |
| 219 | + }, |
| 220 | + { |
| 221 | + href: 'mqq://', |
| 222 | + background: colors.blue, |
| 223 | + iconName: 'paperplane.fill', |
| 224 | + text: 'QQ', |
| 225 | + }, |
| 226 | + { |
| 227 | + href: 'weibo://', |
| 228 | + background: colors.red, |
| 229 | + iconName: 'eye', |
| 230 | + text: '微博', |
| 231 | + }, |
| 232 | + { |
| 233 | + href: 'bilibili://', |
| 234 | + background: colors.pink, |
| 235 | + iconName: 'tv', |
| 236 | + text: '哔哩哔哩', |
| 237 | + }, |
| 238 | + { |
| 239 | + href: 'zhihu://', |
| 240 | + background: colors.blue, |
| 241 | + iconName: 'questionmark', |
| 242 | + text: '知乎', |
| 243 | + }, |
| 244 | + { |
| 245 | + href: 'iqiyi://', |
| 246 | + background: colors.green, |
| 247 | + iconName: 'film', |
| 248 | + text: '爱奇艺', |
| 249 | + }, |
| 250 | + { |
| 251 | + href: 'tencentlaunch1104466820://', |
| 252 | + background: colors.orange, |
| 253 | + iconName: 'gamecontroller', |
| 254 | + text: '王者', |
| 255 | + }, |
| 256 | +] |
| 257 | +EndAwait(() => new Launcher(luancherConfig).init()) |
0 commit comments