提交 cd01f6b4 编写于 作者: D DCloud_LXH

feat(app): darkmode

上级 f1a9e2c4
......@@ -15,9 +15,8 @@ function parseThemeByJsonStr (jsonStr, keys, theme) {
return jsonStr
}
const themeJsonPath = path.join(process.env.UNI_INPUT_DIR, 'theme.json')
function hasTheme () {
function hasTheme (themeLocation = '') {
const themeJsonPath = path.join(process.env.UNI_INPUT_DIR, themeLocation || 'theme.json')
return fs.existsSync(themeJsonPath)
}
......@@ -25,19 +24,24 @@ function darkmode () {
return !!(global.uniPlugin.options || {}).darkmode
}
let themeConfig = {}
module.exports = {
getTheme: () => themeConfig,
darkmode,
hasTheme,
initTheme () {
if (!hasTheme()) {
initTheme (manifestJson = {}) {
const platform = process.env.UNI_PLATFORM
const themeLocation = (manifestJson[platform] || {}).themeLocation
if (!hasTheme(themeLocation)) {
return
}
if (darkmode()) {
return
}
try {
const theme = getJson('theme.json', true)
global.uniPlugin.defaultTheme = theme.light
themeConfig = getJson(themeLocation || 'theme.json', true)
global.uniPlugin.defaultTheme = themeConfig.light
} catch (e) {
console.error(e)
}
......@@ -56,4 +60,4 @@ module.exports = {
}
return JSON.parse(parseThemeByJsonStr(JSON.stringify(json), keys, theme))
}
}
}
......@@ -51,8 +51,6 @@ function renameUsingComponents (jsonObj) {
module.exports = function (content, map) {
this.cacheable && this.cacheable()
initTheme()
let isAppView = false
if (this.resourceQuery) {
const params = loaderUtils.parseQuery(this.resourceQuery)
......@@ -68,6 +66,8 @@ module.exports = function (content, map) {
fs.readFileSync(manifestJsonPath, 'utf8')
)
initTheme(manifestJson)
// this.addDependency(pagesJsonJsPath)
const localePath = path.resolve(process.env.UNI_INPUT_DIR, 'locale')
// 路径不存在时会触发 webpack5 差量编译
......@@ -76,7 +76,7 @@ module.exports = function (content, map) {
}
this.addDependency(manifestJsonPath)
let pagesJson = parsePagesJson(content, {
const originalPagesJson = parsePagesJson(content, {
addDependency: file => {
(process.UNI_PAGES_DEPS || (process.UNI_PAGES_DEPS = new Set())).add(
normalizePath(file)
......@@ -85,7 +85,7 @@ module.exports = function (content, map) {
}
})
if (!pagesJson.pages || pagesJson.pages.length === 0) {
if (!originalPagesJson.pages || originalPagesJson.pages.length === 0) {
console.error(uniI18n.__('pagesLoader.pagesNodeCannotNull'))
process.exit(0)
}
......@@ -94,13 +94,13 @@ module.exports = function (content, map) {
const queryParam = loaderUtils.parseQuery(this.resourceQuery)
if (queryParam) {
if (queryParam.type === 'origin-pages-json') {
return `export default ${JSON.stringify(pagesJson)}`
return `export default ${JSON.stringify(originalPagesJson)}`
}
}
}
const pagesJson = parseTheme(originalPagesJson)
if (global.uniPlugin.defaultTheme) {
pagesJson = parseTheme(pagesJson)
this.addDependency(path.resolve(process.env.UNI_INPUT_DIR, 'theme.json'))
}
......@@ -167,7 +167,7 @@ module.exports = function (content, map) {
}
const jsonFiles = require('./platforms/' + process.env.UNI_PLATFORM)(
pagesJson,
process.env.UNI_PLATFORM === 'app-plus' ? originalPagesJson : pagesJson,
manifestJson,
isAppView
)
......
......@@ -7,6 +7,11 @@ const {
normalizePath,
getFlexDirection
} = require('@dcloudio/uni-cli-shared')
const {
getTheme,
hasTheme,
parseTheme
} = require('@dcloudio/uni-cli-shared/lib/theme')
const {
compileI18nJsonStr
} = require('@dcloudio/uni-i18n')
......@@ -104,6 +109,16 @@ function updateFileFlag (appJson) {
}
}
function _initTheme (appJson, userManifestJson) {
const manifestJson = userManifestJson[process.env.UNI_PLATFORM] || {}
appJson.darkmode = manifestJson.darkmode || false
const themeLocation = manifestJson.themeLocation || ''
if (themeLocation && hasTheme(themeLocation)) {
appJson.themeConfig = getTheme()
}
return appJson
}
module.exports = function (pagesJson, userManifestJson, isAppView) {
const {
app
......@@ -115,10 +130,12 @@ module.exports = function (pagesJson, userManifestJson, isAppView) {
const appJson = app.content
_initTheme(appJson, userManifestJson)
const {
navigationBarTextStyle = 'white',
navigationBarBackgroundColor = '#000000'
} = appJson.window || {}
} = parseTheme(appJson.window) || {}
const TABBAR_HEIGHT = 50
......@@ -279,7 +296,7 @@ module.exports = function (pagesJson, userManifestJson, isAppView) {
// 安全区配置 仅包含 tabBar 的时候才配置
if (!manifestJson.plus.safearea) {
manifestJson.plus.safearea = {
background: appJson.tabBar.backgroundColor || '#FFFFFF',
background: parseTheme(appJson.tabBar).backgroundColor || '#FFFFFF',
bottom: {
offset: 'auto'
}
......@@ -470,7 +487,7 @@ module.exports = function (pagesJson, userManifestJson, isAppView) {
if (args && (args.path || args.pathName)) {
entryPagePath = conditionPagePath = args.path || args.pathName
}
} catch (e) {}
} catch (e) { }
}
let isNVueEntryPage = appJson.nvue && appJson.nvue.entryPagePath
......@@ -521,7 +538,7 @@ module.exports = function (pagesJson, userManifestJson, isAppView) {
pagesJson.tabBar.list.length
) {
const tabBar = (manifestJson.plus.tabBar = Object.assign({},
pagesJson.tabBar
parseTheme(pagesJson.tabBar)
))
const borderStyles = {
black: 'rgba(0,0,0,0.4)',
......@@ -546,9 +563,9 @@ module.exports = function (pagesJson, userManifestJson, isAppView) {
const item = tabBar.list.find(
page =>
page.pagePath ===
(process.env.UNI_USING_NATIVE
? appJson.entryPagePath
: entryPagePath)
(process.env.UNI_USING_NATIVE
? appJson.entryPagePath
: entryPagePath)
)
if (item) {
tabBar.child = ['lauchwebview']
......@@ -634,7 +651,7 @@ function initUniStatistics (manifestJson) {
let spaces = []
try {
spaces = JSON.parse(process.env.UNI_CLOUD_PROVIDER)
} catch (e) {}
} catch (e) { }
if (!Array.isArray(spaces) || !spaces.length) {
return
}
......
......@@ -18,7 +18,13 @@ const alipayWindowMap = {
navigationBarShadow: 'navigationBarShadow',
titleImage: 'titleImage',
transparentTitle: 'transparentTitle',
titlePenetrate: 'titlePenetrate'
titlePenetrate: 'titlePenetrate',
barButtonTheme: {
key: 'navigationBarTextStyle',
transform: function (value) {
}
}
}
const alipayTabBarMap = {
......
......@@ -5,15 +5,16 @@ import { sortObject } from 'uni-shared'
let systemInfo = {}
let _initSystemInfo = true
function weexGetSystemInfoSync () {
export function weexGetSystemInfoSync () {
if (!_initSystemInfo) return
const { getSystemInfoSync } = weex.requireModule('plus')
systemInfo = getSystemInfoSync()
if (typeof systemInfo === 'string') {
try {
systemInfo = JSON.parse(systemInfo)
} catch (error) {}
} catch (error) { }
}
return systemInfo
}
export function getDeviceInfo () {
......@@ -47,7 +48,7 @@ export function getAppBaseInfo () {
hostPackageName, hostName, osLanguage,
hostVersion, hostLanguage, hostTheme,
appId, appName, appVersion, appVersionCode,
appWgtVersion
appWgtVersion, osTheme
} = systemInfo
const appLanguage = uni
......@@ -73,7 +74,7 @@ export function getAppBaseInfo () {
hostFontSizeSetting: undefined,
language: osLanguage,
SDKVersion: '',
theme: undefined,
theme: hostTheme || osTheme,
version: plus.runtime.innerVersion
}
}
......@@ -112,7 +113,9 @@ export function getSystemInfo () {
delete _systemInfo.screenTop
delete _systemInfo.enableDebug
delete _systemInfo.theme
if (!__uniConfig.darkmode) {
delete _systemInfo.theme
}
return sortObject(_systemInfo)
}
......@@ -7,6 +7,8 @@ import {
requireNativePlugin
} from '../bridge'
import { useTabBarThemeChange } from './theme'
const TABBAR_HEIGHT = 50
let config
......@@ -17,6 +19,10 @@ let visible = true
let tabBar
function setTabBarItems (style) {
tabBar && tabBar.setTabBarItems(style)
}
/**
* 设置角标
* @param {string} type
......@@ -60,9 +66,9 @@ function setTabBarItem (index, text, iconPath, selectedIconPath, visible, iconfo
}
if (selectedIconPath) {
item.selectedIconPath = getRealPath(selectedIconPath)
}
if (iconfont !== undefined) {
item.iconfont = iconfont
}
if (iconfont !== undefined) {
item.iconfont = iconfont
}
if (visible !== undefined) {
item.visible = config.list[index].visible = visible
......@@ -71,7 +77,7 @@ function setTabBarItem (index, text, iconPath, selectedIconPath, visible, iconfo
const tabbarItems = config.list.map(item => ({ visible: item.visible }))
tabbarItems[index] = item
tabBar && tabBar.setTabBarItems({ list: tabbarItems })
setTabBarItems({ list: tabbarItems })
} else {
tabBar && tabBar.setTabBarItem(item)
}
......@@ -128,6 +134,8 @@ export default {
tabBar && tabBar.onMidButtonClick(() => {
publish('onTabBarMidButtonTap', {})
})
useTabBarThemeChange(tabBar, options)
},
indexOf (page) {
const config = this.config
......
import { normallizeStyles } from 'uni-shared'
import { weexGetSystemInfoSync } from '../api/device/system'
const ON_THEME_CHANGE = 'api.onThemeChange'
function onThemeChange (callback = () => { }) {
UniServiceJSBridge.on(ON_THEME_CHANGE, callback)
}
function offThemeChange (callback = () => { }) {
UniServiceJSBridge.off(ON_THEME_CHANGE, callback)
}
export function parseTheme (pageStyle) {
let parsedStyle = {}
if (__uniConfig.darkmode) {
let theme = 'light'
const systemInfo = weexGetSystemInfoSync()
if (systemInfo) {
theme = systemInfo.hostTheme || systemInfo.osTheme
}
parsedStyle = normallizeStyles(pageStyle, __uniConfig.themeConfig, theme)
}
return __uniConfig.darkmode ? parsedStyle : pageStyle
}
export function useTabBarThemeChange (tabBar, options) {
if (__uniConfig.darkmode) {
const fn = () => {
const {
list = [], color, selectedColor,
backgroundColor, borderStyle
} = parseTheme(options, false)
const tabbarStyle = {
color,
selectedColor,
backgroundColor,
borderStyle
}
tabBar && tabBar.setTabBarStyle(tabbarStyle)
tabBar && tabBar.setTabBarItems({
list: list.map((item) => ({
iconPath: item.iconPath,
selectedIconPath: item.selectedIconPath
}))
})
// TODO 暂未实现
// tabBar && tabBar.setAnimationAlphaBGColor(parseTheme((__uniConfig.window || {}).backgroundColor, false))
}
fn()
onThemeChange(fn)
}
}
export function useWebviewThemeChange (webview, getWebviewStyle) {
if (__uniConfig.darkmode) {
const fn = () => {
const {
animationAlphaBGColor, background,
backgroundColorBottom, backgroundColorTop,
titleNView: { backgroundColor, titleColor } = {}
} = getWebviewStyle()
webview && webview.setStyle({
animationAlphaBGColor,
background,
backgroundColorBottom,
backgroundColorTop,
titleNView: {
backgroundColor,
titleColor
}
})
}
onThemeChange(fn)
webview.addEventListener('close', () => offThemeChange(fn))
}
}
......@@ -30,6 +30,8 @@ import {
onWebviewPopGesture
} from './on-webview-pop-gesture'
import { useWebviewThemeChange } from '../theme'
export let preloadWebview
let id = 2
......@@ -71,21 +73,26 @@ function getDebugRefresh (path, query, routeOptions) {
export function createWebview (path, routeOptions, query, extras = {}) {
if (routeOptions.meta.isNVue) {
const webviewId = id++
const webviewStyle = parseWebviewStyle(
const getWebviewStyle = () => parseWebviewStyle(
webviewId,
path,
routeOptions
)
const webviewId = id++
const webviewStyle = getWebviewStyle()
webviewStyle.uniPageUrl = getUniPageUrl(path, query)
if (process.env.NODE_ENV !== 'production') {
console.log('[uni-app] createWebview', webviewId, path, webviewStyle)
}
// android 需要使用
webviewStyle.isTab = !!routeOptions.meta.isTabBar
return plus.webview.create('', String(webviewId), webviewStyle, Object.assign({
const webview = plus.webview.create('', String(webviewId), webviewStyle, Object.assign({
nvue: true
}, extras))
useWebviewThemeChange(webview, getWebviewStyle)
return webview
}
if (id === 2) { // 如果首页非 nvue,则直接返回 Launch Webview
return plus.webview.getLaunchWebview()
......@@ -97,11 +104,12 @@ export function createWebview (path, routeOptions, query, extras = {}) {
export function initWebview (webview, routeOptions, path, query) {
// 首页或非 nvue 页面
if (webview.id === '1' || !routeOptions.meta.isNVue) {
const webviewStyle = parseWebviewStyle(
const getWebviewStyle = () => parseWebviewStyle(
parseInt(webview.id),
'',
routeOptions
)
const webviewStyle = getWebviewStyle()
webviewStyle.uniPageUrl = getUniPageUrl(path, query)
......@@ -115,6 +123,8 @@ export function initWebview (webview, routeOptions, path, query) {
console.log('[uni-app] updateWebview', webviewStyle)
}
useWebviewThemeChange(webview, getWebviewStyle)
webview.setStyle(webviewStyle)
}
......
......@@ -4,6 +4,8 @@ import { parsePullToRefresh } from './pull-to-refresh-parser'
import { parseStyleUnit } from './style-unit-parser'
import { parseTheme } from '../../theme'
const WEBVIEW_STYLE_BLACKLIST = [
'navigationBarBackgroundColor',
'navigationBarTextStyle',
......@@ -21,25 +23,27 @@ const WEBVIEW_STYLE_BLACKLIST = [
'pullToRefresh'
]
export function parseWebviewStyle (id, path, routeOptions = {}) {
export function parseWebviewStyle (id, path, _routeOptions = {}) {
const webviewStyle = {
bounce: 'vertical'
}
// 合并
routeOptions.window = parseStyleUnit(
_routeOptions.window = parseStyleUnit(
Object.assign(
JSON.parse(JSON.stringify(__uniConfig.window || {})),
routeOptions.window || {}
_routeOptions.window || {}
)
)
Object.keys(routeOptions.window).forEach(name => {
Object.keys(_routeOptions.window).forEach(name => {
if (WEBVIEW_STYLE_BLACKLIST.indexOf(name) === -1) {
webviewStyle[name] = routeOptions.window[name]
webviewStyle[name] = _routeOptions.window[name]
}
})
const routeOptions = parseTheme(_routeOptions)
const backgroundColor = routeOptions.window.backgroundColor
if (
/^#[a-z0-9]{6}$/i.test(backgroundColor) ||
......@@ -51,6 +55,15 @@ export function parseWebviewStyle (id, path, routeOptions = {}) {
if (!webviewStyle.backgroundColorTop) {
webviewStyle.backgroundColorTop = backgroundColor
}
if (!webviewStyle.backgroundColorBottom) {
webviewStyle.backgroundColorBottom = backgroundColor
}
if (!webviewStyle.animationAlphaBGColor) {
webviewStyle.animationAlphaBGColor = backgroundColor
}
if (typeof webviewStyle.webviewBGTransparent === 'undefined') {
webviewStyle.webviewBGTransparent = true
}
}
const titleNView = parseTitleNView(id, routeOptions)
......
......@@ -4,3 +4,4 @@ export * from './color'
export * from './query'
export * from './platform'
export * from './callback'
export * from './theme'
import { isPlainObject, isStr } from './util'
const borderStyles = {
black: 'rgba(0,0,0,0.4)',
white: 'rgba(255,255,255,0.4)'
}
export function normalizeTabBarStyles (borderStyle) {
if (borderStyle && borderStyle in borderStyles) {
return borderStyles[borderStyle]
}
return borderStyle
}
export function normallizeStyles (pageStyle, themeConfig, mode = 'light') {
const modeStyle = themeConfig[mode]
const styles = {}
if (!modeStyle) {
return styles
}
Object.keys(pageStyle).forEach((key) => {
const styleItem = pageStyle[key] // Object Array String
styles[key] = (() => {
if (isPlainObject(styleItem)) {
return normallizeStyles(styleItem, themeConfig, mode)
} else if (Array.isArray(styleItem)) {
return styleItem.map((item) => isPlainObject(item)
? normallizeStyles(item, themeConfig, mode)
: item)
} else if (isStr(styleItem) && styleItem.startsWith('@')) {
const _key = styleItem.replace('@', '')
let _styleItem = modeStyle[_key]
switch (key) {
case 'borderStyle':
_styleItem = normalizeTabBarStyles(_styleItem)
break
}
return _styleItem
}
return styleItem
})()
})
return styles
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册