提交 40837b8a 编写于 作者: DCloud-yyl's avatar DCloud-yyl

同步代码@HBuilderX4.34

上级 cc64cc0a
...@@ -158,6 +158,9 @@ function fingerPrintAvailable() { ...@@ -158,6 +158,9 @@ function fingerPrintAvailable() {
userAuth.getAvailableStatus(userAuth.UserAuthType.FINGERPRINT, userAuth.AuthTrustLevel.ATL1); userAuth.getAvailableStatus(userAuth.UserAuthType.FINGERPRINT, userAuth.AuthTrustLevel.ATL1);
return true return true
} catch (error) { } catch (error) {
if ([userAuth.UserAuthResultCode.NOT_ENROLLED, userAuth.UserAuthResultCode.PIN_EXPIRED].includes((error as BusinessError).code)) {
return true
}
return false return false
} }
} }
...@@ -167,6 +170,9 @@ function faceAvailable() { ...@@ -167,6 +170,9 @@ function faceAvailable() {
userAuth.getAvailableStatus(userAuth.UserAuthType.FACE, userAuth.AuthTrustLevel.ATL1); userAuth.getAvailableStatus(userAuth.UserAuthType.FACE, userAuth.AuthTrustLevel.ATL1);
return true return true
} catch (error) { } catch (error) {
if ([userAuth.UserAuthResultCode.NOT_ENROLLED, userAuth.UserAuthResultCode.PIN_EXPIRED].includes((error as BusinessError).code)) {
return true
}
return false return false
} }
} }
......
{
"id": "uni-chooseLocation",
"displayName": "uni-chooseLocation",
"version": "1.0.0",
"description": "uni-chooseLocation",
"keywords": [
"uni-chooseLocation"
],
"repository": "",
"engines": {
"HBuilderX": "^3.6.8"
},
"dcloudext": {
"type": "uts",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "",
"data": "",
"permissions": ""
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [
"uni-framework",
"uni-theme",
"uni-getSystemInfo",
"uni-getLocation",
"uni-cloud-client",
"uni-getLocation",
"uni-map-tencent"
],
"uni-ext-api": {
"uni": {
"chooseLocation": {
"name": "chooseLocation",
"app": {
"js": true,
"kotlin": true,
"swift": true,
"arkts": false
}
}
}
},
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "u",
"aliyun": "u"
},
"client": {
"Vue": {
"vue2": "u",
"vue3": "u"
},
"App": {
"app-android": "u",
"app-ios": "u"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}
# uni-actionSheet
### 开发文档
[UTS 语法](https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html)
[UTS API插件](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html)
[UTS 组件插件](https://uniapp.dcloud.net.cn/plugin/uts-component.html)
[Hello UTS](https://gitcode.net/dcloud/hello-uts)
\ No newline at end of file
import { registerSystemRoute } from "@dcloudio/uni-runtime";
import uniChooseLocationPage from "@/uni_modules/uni-chooseLocation/pages/chooseLocation/chooseLocation.vue";
import {
ChooseLocation,
ChooseLocationOptions,
ChooseLocationSuccessImpl,
ChooseLocationFailImpl
} from "../interface.uts";
export const chooseLocation: ChooseLocation = function (options: ChooseLocationOptions) {
registerSystemRoute("uni:chooseLocation", uniChooseLocationPage);
const uuid = Date.now() + '' + Math.floor(Math.random() * 1e7)
const baseEventName = `uni_choose_location_${uuid}`
const readyEventName = `${baseEventName}_ready`
const optionsEventName = `${baseEventName}_options`
const successEventName = `${baseEventName}_success`
const failEventName = `${baseEventName}_fail`
uni.$on(readyEventName, () => {
uni.$emit(optionsEventName, JSON.parse(JSON.stringify(options)));
})
uni.$on(successEventName, (result: UTSJSONObject) => {
let name = result['name'] as string;
let address = result['address'] as string;
let latitude = result.getNumber('latitude') as number;
let longitude = result.getNumber('longitude') as number;
options.success?.(new ChooseLocationSuccessImpl(name, address, latitude, longitude))
})
uni.$on(failEventName, () => {
options.fail?.(new ChooseLocationFailImpl())
})
uni.openDialogPage({
url: `uni:chooseLocation?readyEventName=${readyEventName}&optionsEventName=${optionsEventName}&successEventName=${successEventName}&failEventName=${failEventName}`,
fail(err) {
options.fail?.(new ChooseLocationFailImpl(`showActionSheet failed, ${err.errMsg}`, 4))
uni.$off(readyEventName)
uni.$off(successEventName)
uni.$off(failEventName)
}
})
};
import { defineAsyncApi, registerSystemRoute } from "@dcloudio/uni-runtime";
import uniChooseLocationPage from "@/uni_modules/uni-chooseLocation/pages/chooseLocation/chooseLocation.vue";
import { ChooseLocation, ChooseLocationOptions, ChooseLocationSuccess } from "../interface.uts"
export const chooseLocation: ChooseLocation = defineAsyncApi('chooseLocation', (
options: ChooseLocationOptions, { resolve, reject }
) => {
registerSystemRoute("uni:chooseLocation", uniChooseLocationPage, {
disableSwipeBack: false
});
const uuid = Date.now() + '' + Math.floor(Math.random() * 1e7)
const baseEventName = `uni_choose_location_${uuid}`
const readyEventName = `${baseEventName}_ready`
const optionsEventName = `${baseEventName}_options`
const successEventName = `${baseEventName}_success`
const failEventName = `${baseEventName}_fail`
uni.$on(readyEventName, () => {
uni.$emit(optionsEventName, JSON.parse(JSON.stringify(options)))
})
uni.$on(successEventName, (result: ChooseLocationSuccess) => {
resolve(result)
})
uni.$on(failEventName, () => {
reject('cancel', {
errCode: 1
})
})
uni.openDialogPage({
url: `uni:chooseLocation?readyEventName=${readyEventName}&optionsEventName=${optionsEventName}&successEventName=${successEventName}&failEventName=${failEventName}`,
fail(err) {
options.fail?.({ errMsg: `chooseLocation:fail ${err.errMsg}`, errCode: 4 })
uni.$off(readyEventName)
uni.$off(successEventName)
uni.$off(failEventName)
}
})
});
/**
* 错误码
*/
export type ChooseLocationErrorCode =
/**
* 取消
*/
1 |
/**
* 框架内部错误
*/
4;
export interface ChooseLocationSuccess extends AsyncApiSuccessResult {
name : string,
address : string,
latitude : number,
longitude : number
}
type ChooseLocationSuccessCallback = (result : ChooseLocationSuccess) => void
export interface ChooseLocationFail extends IUniError {
errCode : ChooseLocationErrorCode
}
type ChooseLocationFailCallback = (result : ChooseLocationFail) => void
export type ChooseLocationComplete = AsyncApiResult
type ChooseLocationCompleteCallback = (result : ChooseLocationComplete) => void
/**
* uni.chooseLocation函数参数定义
*/
export type ChooseLocationOptions = {
/**
* 指示位置的经度
*/
latitude ?: number | null,
/**
* 指示位置的纬度
*/
longitude ?: number | null,
/**
* 指示位置的名称
*/
keyword ?: string | null,
/**
* 接口调用成功的回调函数
*/
success ?: ChooseLocationSuccessCallback | null,
/**
* 接口调用失败的回调函数
*/
fail ?: ChooseLocationFailCallback | null,
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete ?: ChooseLocationCompleteCallback | null
};
/**
* 打开地图选择位置
*
* @param {ChooseLocationOptions} options
* @tutorial https://doc.dcloud.net.cn/uni-app-x/api/prompt.html#chooselocation
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "5.0",
* "uniVer": "√",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "12.0",
* "uniVer": "√",
* "unixVer": "4.11"
* },
* "harmony": {
* "osVer": "3.0",
* "uniVer": "4.23",
* "unixVer": "x"
* }
* },
* "web": {
* "uniVer": "√",
* "unixVer": "4.0"
* }
* }
*/
export type ChooseLocation = (options : ChooseLocationOptions) => void;
export interface Uni {
/**
* @description 打开地图选择位置
* @example
* ```typescript
uni.chooseLocation({
success: (res) => {
console.log('res: ', res)
},
fail: (err) => {
console.log('err: ', err)
},
complete: (res) => {
console.log('complete: ', res)
}
});
* ```
* @tutorial https://doc.dcloud.net.cn/uni-app-x/api/choose-location.html
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "5.0",
* "uniVer": "√",
* "unixVer": "4.33"
* },
* "ios": {
* "osVer": "12.0",
* "uniVer": "√",
* "unixVer": "4.33"
* },
* "harmony": {
* "osVer": "3.0",
* "uniVer": "4.23",
* "unixVer": "x"
* }
* },
* "web": {
* "uniVer": "√",
* "unixVer": "4.0"
* }
* }
*/
chooseLocation(options : ChooseLocationOptions) : void;
}
// #ifdef APP-ANDROID
// @ts-expect-error
export class ChooseLocationSuccessImpl extends AsyncApiSuccessResult implements ChooseLocationSuccess {
name : string
address : string
latitude : number
longitude : number
// @ts-expect-error
override errMsg : string
constructor(name : string, address : string, latitude : number, longitude : number, errMsg : string = 'chooseLocation:ok') {
super()
this.errMsg = errMsg
this.name = name
this.address = address
this.latitude = latitude
this.longitude = longitude
}
}
export class ChooseLocationFailImpl extends UniError implements ChooseLocationFail {
override errCode : ChooseLocationErrorCode
constructor(errMsg : string = 'chooseLocation:fail cancel', errCode : ChooseLocationErrorCode = 4) {
super(errMsg)
this.errCode = errCode
}
}
// #endif
import { defineAsyncApi, registerSystemRoute } from "@dcloudio/uni-runtime";
import uniChooseLocationPage from "@/uni_modules/uni-chooseLocation/pages/chooseLocation/chooseLocation.vue";
import { ChooseLocation, ChooseLocationOptions, ChooseLocationSuccess, ChooseLocationFail } from "../interface.uts"
export const chooseLocation: ChooseLocation = defineAsyncApi('chooseLocation', (
options: ChooseLocationOptions, { resolve, reject }
) => {
registerSystemRoute("uni:chooseLocation", uniChooseLocationPage);
const uuid = Date.now() + '' + Math.floor(Math.random() * 1e7)
const baseEventName = `uni_choose_location_${uuid}`
const readyEventName = `${baseEventName}_ready`
const optionsEventName = `${baseEventName}_options`
const successEventName = `${baseEventName}_success`
const failEventName = `${baseEventName}_fail`
uni.$on(readyEventName, () => {
uni.$emit(optionsEventName, JSON.parse(JSON.stringify(options)))
})
uni.$on(successEventName, (result: ChooseLocationSuccess) => {
resolve(result)
})
uni.$on(failEventName, () => {
reject('cancel', {
errCode: 1
})
})
uni.openDialogPage({
url: `uni:chooseLocation?readyEventName=${readyEventName}&optionsEventName=${optionsEventName}&successEventName=${successEventName}&failEventName=${failEventName}`,
fail(err) {
options.fail?.({ errMsg: `chooseLocation:fail ${err.errMsg}`, errCode: 4 } as ChooseLocationFail)
uni.$off(readyEventName)
uni.$off(successEventName)
uni.$off(failEventName)
}
})
});
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
"name": "createInnerAudioContext", "name": "createInnerAudioContext",
"app": { "app": {
"js": false, "js": false,
"kotlin": false, "kotlin": true,
"swift": false, "swift": false,
"arkts": true "arkts": true
} }
......
{
"dependencies": [
"com.google.android.exoplayer:exoplayer-core:2.18.0"
]
}
\ No newline at end of file
import { InnerAudioContext, CreateInnerAudioContext } from "../interface.uts"
export { CreateInnerAudioContextFailImpl } from '../unierror.uts'
export const createInnerAudioContext : CreateInnerAudioContext = function () : InnerAudioContext {
let player = new AudioPlayer()
return player
}
\ No newline at end of file
import { media } from '@kit.MediaKit'; import { media } from '@kit.MediaKit';
import { audio } from '@kit.AudioKit'; import { audio } from '@kit.AudioKit';
import { InnerAudioContext, CreateInnerAudioContext } from '../interface.uts'; import { InnerAudioContext, CreateInnerAudioContext, type ICreateInnerAudioContextFail } from '../interface.uts';
import { API_CREATE_INNER_AUDIO_CONTEXT } from '../protocol.uts'; import { API_CREATE_INNER_AUDIO_CONTEXT } from '../protocol.uts';
import { getFdFromUriOrSandBoxPath, isFileUri, isSandboxPath, AudioPlayerCallback, AudioPlayerError } from './utils.uts'; import { getFdFromUriOrSandBoxPath, isFileUri, isSandboxPath, AudioPlayerCallback, AudioPlayerError } from './utils.uts';
...@@ -254,7 +254,7 @@ class AudioPlayer implements InnerAudioContext { ...@@ -254,7 +254,7 @@ class AudioPlayer implements InnerAudioContext {
onTimeUpdate(callback: (result: any) => void): void { onTimeUpdate(callback: (result: any) => void): void {
this.audioPlayerCallback.onTimeUpdate(callback) this.audioPlayerCallback.onTimeUpdate(callback)
} }
onError(callback: (result: any) => void): void { onError(callback: (result: ICreateInnerAudioContextFail) => void): void {
this.audioPlayerCallback.onError(callback) this.audioPlayerCallback.onError(callback)
} }
onWaiting(callback: (result: any) => void): void { onWaiting(callback: (result: any) => void): void {
...@@ -284,7 +284,7 @@ class AudioPlayer implements InnerAudioContext { ...@@ -284,7 +284,7 @@ class AudioPlayer implements InnerAudioContext {
offTimeUpdate(callback: (result: any) => void): void { offTimeUpdate(callback: (result: any) => void): void {
this.audioPlayerCallback.offTimeUpdate(callback) this.audioPlayerCallback.offTimeUpdate(callback)
} }
offError(callback: (result: any) => void): void { offError(callback: (result: ICreateInnerAudioContextFail) => void): void {
this.audioPlayerCallback.offError(callback) this.audioPlayerCallback.offError(callback)
} }
offWaiting(callback: (result: any) => void): void { offWaiting(callback: (result: any) => void): void {
......
import { CreateInnerAudioContextErrorCode, ICreateInnerAudioContextFail } from "./interface.uts"
/**
* 错误主题
*/
export const CreateInnerAudioUniErrorSubject = 'uni-createInnerAudioContext';
/**
* 错误码
* @UniError
*/
export const CreateInnerAudioContextUniErrors : Map<CreateInnerAudioContextErrorCode, string> = new Map([
/**
* 系统错误
*/
[1107601, 'system error.'],
/**
* 网络错误
*/
[1107602, 'network error.'],
/**
* 文件错误
*/
[1107603, 'file error.'],
/**
* 格式错误
*/
[1107604, 'format error.'],
/**
* 未知错误
*/
[1107605, 'unknown error.'],
/**
* 播放路径不能为空
*/
[1107609, 'empty src.'],
]);
export class CreateInnerAudioContextFailImpl extends UniError implements ICreateInnerAudioContextFail {
constructor(errCode : CreateInnerAudioContextErrorCode) {
super();
this.errSubject = CreateInnerAudioUniErrorSubject;
this.errCode = errCode;
this.errMsg = CreateInnerAudioContextUniErrors[errCode] ?? "";
}
}
\ No newline at end of file
...@@ -3,14 +3,28 @@ import { ...@@ -3,14 +3,28 @@ import {
ANIMATION_TYPE, ANIMATION_TYPE,
getCurrentPage, getCurrentPage,
Page, Page,
isSystemDialogPage,
} from '@dcloudio/uni-runtime' } from '@dcloudio/uni-runtime'
import {
DEFAULT_ANIMATION_DURATION,
DEFAULT_ANIMATION_OUT,
} from '../constants.uts'
import { CloseDialogPageOptions } from '../interface.uts' import { CloseDialogPageOptions } from '../interface.uts'
import { CloseDialogPageSuccessImpl, CloseDialogPageFailImpl } from '../unierror.uts' import { CloseDialogPageSuccessImpl, CloseDialogPageFailImpl } from '../unierror.uts'
export const closeDialogPage = (options: CloseDialogPageOptions | null) => { export const closeDialogPage = (options: CloseDialogPageOptions | null) => {
if (options?.animationType === 'pop-out') {
options.animationType = 'none'
}
const closeOptions = new Map<string, any | null>([ const closeOptions = new Map<string, any | null>([
[ANIMATION_TYPE, 'none'], [
[ANIMATION_DURATION, 0], ANIMATION_TYPE,
options?.animationType ?? DEFAULT_ANIMATION_OUT,
],
[
ANIMATION_DURATION,
options?.animationDuration ?? DEFAULT_ANIMATION_DURATION,
],
]) ])
if (options?.dialogPage === null) { if (options?.dialogPage === null) {
const currentPage = getCurrentPage() const currentPage = getCurrentPage()
...@@ -35,6 +49,10 @@ export const closeDialogPage = (options: CloseDialogPageOptions | null) => { ...@@ -35,6 +49,10 @@ export const closeDialogPage = (options: CloseDialogPageOptions | null) => {
const dialogPage = options?.dialogPage! const dialogPage = options?.dialogPage!
const currentPages = getCurrentPages() const currentPages = getCurrentPages()
const parentPage = dialogPage.getParentPage() const parentPage = dialogPage.getParentPage()
if (isSystemDialogPage(dialogPage)) {
(dialogPage.$vm as Page).$close(closeOptions)
return
}
if ((dialogPage.$vm as Page).$dialog === null || if ((dialogPage.$vm as Page).$dialog === null ||
currentPages.indexOf(parentPage) === -1 || currentPages.indexOf(parentPage) === -1 ||
parentPage!.getDialogPages().indexOf(dialogPage) === -1) { parentPage!.getDialogPages().indexOf(dialogPage) === -1) {
...@@ -44,7 +62,7 @@ export const closeDialogPage = (options: CloseDialogPageOptions | null) => { ...@@ -44,7 +62,7 @@ export const closeDialogPage = (options: CloseDialogPageOptions | null) => {
options.complete?.(errRes) options.complete?.(errRes)
} }
} else { } else {
(dialogPage!.$vm as Page).$close(closeOptions) (dialogPage.$vm as Page).$close(closeOptions)
if (options !== null) { if (options !== null) {
const successRes = new CloseDialogPageSuccessImpl() const successRes = new CloseDialogPageSuccessImpl()
options.success?.(successRes) options.success?.(successRes)
......
...@@ -5,6 +5,11 @@ import { ...@@ -5,6 +5,11 @@ import {
navigateDialogPage, navigateDialogPage,
} from '@dcloudio/uni-runtime' } from '@dcloudio/uni-runtime'
import { normalizeRouteOptions } from '../protocols.uts' import { normalizeRouteOptions } from '../protocols.uts'
import {
DEFAULT_ANIMATION_DURATION,
DEFAULT_ANIMATION_IN,
} from '../constants.uts'
import { OpenDialogPageOptions } from '../interface.uts' import { OpenDialogPageOptions } from '../interface.uts'
import { OpenDialogPageSuccessImpl, OpenDialogPageFailImpl } from '../unierror.uts' import { OpenDialogPageSuccessImpl, OpenDialogPageFailImpl } from '../unierror.uts'
...@@ -34,15 +39,24 @@ export const openDialogPage = (options: OpenDialogPageOptions): UniPage | null = ...@@ -34,15 +39,24 @@ export const openDialogPage = (options: OpenDialogPageOptions): UniPage | null =
options.url = normalizeRouteOptionsResult.url options.url = normalizeRouteOptionsResult.url
if (options.animationType === 'pop-in') {
options.animationType = 'none'
}
const dialogPage = navigateDialogPage( const dialogPage = navigateDialogPage(
options.url as string, options.url as string,
new Map<string, any | null>([ new Map<string, any | null>([
[ANIMATION_TYPE, 'none'], [
[ANIMATION_DURATION, 0], ANIMATION_TYPE,
options.animationType ?? DEFAULT_ANIMATION_IN,
],
[
ANIMATION_DURATION,
options.animationDuration ?? DEFAULT_ANIMATION_DURATION,
],
]), ]),
NAVIGATE_TO, NAVIGATE_TO,
navigationStart, navigationStart,
new Map([ new Map<string, any | null>([
['disableEscBack', options.disableEscBack], ['disableEscBack', options.disableEscBack],
['parentPage', options.parentPage], ['parentPage', options.parentPage],
]), ]),
......
export const DEFAULT_ANIMATION_IN = 'none'
export const DEFAULT_ANIMATION_OUT = 'none'
export const DEFAULT_ANIMATION_DURATION = 300
export const DEFAULT_ANIMATION_NAVIGATE_BACK = 'auto'
export const ANIMATION_IN = [
'slide-in-right',
'slide-in-left',
'slide-in-top',
'slide-in-bottom',
'fade-in',
'zoom-out',
// 'zoom-fade-out',
// 'pop-in',
'none',
]
export const ANIMATION_OUT = [
'slide-out-right',
'slide-out-left',
'slide-out-top',
'slide-out-bottom',
'fade-out',
'zoom-in',
// 'zoom-fade-in',
// 'pop-out',
'none',
]
...@@ -25,6 +25,9 @@ export function normalizeRouteOptions( ...@@ -25,6 +25,9 @@ export function normalizeRouteOptions(
url, url,
} as NormalizeRouteOptionsResult } as NormalizeRouteOptionsResult
} }
if (url.startsWith('uni:')) {
return { errMsg: '', url } as NormalizeRouteOptionsResult
}
// 格式化为绝对路径路由 // 格式化为绝对路径路由
url = normalizeRoute(url) url = normalizeRoute(url)
const pagePath = parseUrl(url!).path const pagePath = parseUrl(url!).path
...@@ -86,7 +89,7 @@ function getRealRoute(fromRoute: string, toRoute: string): string { ...@@ -86,7 +89,7 @@ function getRealRoute(fromRoute: string, toRoute: string): string {
const toRouteArray = toRoute.split('/') const toRouteArray = toRoute.split('/')
const toRouteLength = toRouteArray.length const toRouteLength = toRouteArray.length
let i = 0 let i = 0
for (; i < toRouteLength && toRouteArray[i] == '..'; i++) { for (;i < toRouteLength && toRouteArray[i] == '..';i++) {
// noop // noop
} }
toRouteArray.splice(0, i) toRouteArray.splice(0, i)
......
...@@ -7,6 +7,7 @@ import { ...@@ -7,6 +7,7 @@ import {
export class OpenDialogPageSuccessImpl extends AsyncApiSuccessResult { export class OpenDialogPageSuccessImpl extends AsyncApiSuccessResult {
override errMsg: string override errMsg: string
constructor(errMsg: string = 'openDialogPage: ok') { constructor(errMsg: string = 'openDialogPage: ok') {
super()
this.errMsg = errMsg this.errMsg = errMsg
} }
} }
...@@ -22,6 +23,7 @@ export class OpenDialogPageFailImpl extends UniError implements OpenDialogPageFa ...@@ -22,6 +23,7 @@ export class OpenDialogPageFailImpl extends UniError implements OpenDialogPageFa
export class CloseDialogPageSuccessImpl extends AsyncApiSuccessResult { export class CloseDialogPageSuccessImpl extends AsyncApiSuccessResult {
override errMsg: string override errMsg: string
constructor(errMsg: string = 'closeDialogPage: ok') { constructor(errMsg: string = 'closeDialogPage: ok') {
super()
this.errMsg = errMsg this.errMsg = errMsg
} }
} }
......
import { Emitter } from '@dcloudio/uni-runtime' import { Emitter } from '@dcloudio/uni-runtime'
import { $Emit, $Off, $On, $Once } from '../interface.uts' import { $Off, $On, $Once } from '../interface.uts'
const emitter = new Emitter() const emitter = new Emitter()
...@@ -16,7 +16,6 @@ export const $once = defineSyncApi<$Once>('$once', (eventName, callback): number ...@@ -16,7 +16,6 @@ export const $once = defineSyncApi<$Once>('$once', (eventName, callback): number
return emitter.once(eventName, callback) return emitter.once(eventName, callback)
}) })
export const $emit = defineSyncApi<$Emit>('$emit', (eventName, arg) => { export function $emit(eventName: string, ...args: Array<any | null>): void {
// TODO muti args emitter.emit(eventName, ...args)
emitter.emit(eventName, arg) }
})
import { import {
Emitter Emitter,
getCurrentMP
} from '@dcloudio/uni-runtime' } from '@dcloudio/uni-runtime'
import { import {
$Emit, $Emit,
...@@ -21,32 +22,46 @@ interface IUniEventEmitter { ...@@ -21,32 +22,46 @@ interface IUniEventEmitter {
emit: (eventName: string, ...args: (Object | undefined | null)[]) => void emit: (eventName: string, ...args: (Object | undefined | null)[]) => void
} }
const emitter: IUniEventEmitter = new Emitter() as IUniEventEmitter const emitterStore = new Map<string, IUniEventEmitter>()
function getEmitter(): IUniEventEmitter {
const mp = getCurrentMP()
const id = mp.id as string
if (emitterStore.has(id)) {
return emitterStore.get(id) as IUniEventEmitter
}
const emitter = new Emitter() as IUniEventEmitter
emitterStore.set(id, emitter)
mp.on('beforeClose', () => {
emitterStore.delete(id)
})
return emitter
}
export const $on: $On = defineSyncApi<number>( export const $on: $On = defineSyncApi<number>(
API_$_ON, API_$_ON,
(eventName: string, callback: Function) => { (eventName: string, callback: Function) => {
return emitter.on(eventName, callback) return getEmitter().on(eventName, callback)
} }
) as $On ) as $On
export const $once: $Once = defineSyncApi<number>( export const $once: $Once = defineSyncApi<number>(
API_$_ONCE, API_$_ONCE,
(eventName: string, callback: Function) => { (eventName: string, callback: Function) => {
return emitter.once(eventName, callback) return getEmitter().once(eventName, callback)
} }
) as $Once ) as $Once
export const $off: $Off = defineSyncApi<void>( export const $off: $Off = defineSyncApi<void>(
API_$_OFF, API_$_OFF,
(eventName: string, callback: Function) => { (eventName: string, callback: Function) => {
emitter.off(eventName, callback) getEmitter().off(eventName, callback)
} }
) as $Off ) as $Off
export const $emit: $Emit = defineSyncApi<void>( export const $emit: $Emit = defineSyncApi<void>(
API_$_EMIT, API_$_EMIT,
(eventName: string, ...args: (Object | undefined | null)[]) => { (eventName: string, ...args: (Object | undefined | null)[]) => {
emitter.emit(eventName, ...args) getEmitter().emit(eventName, ...args)
} }
) as $Emit ) as $Emit
...@@ -6,7 +6,7 @@ export type $Once = (eventName: string, callback: $OnceCallback) => number ...@@ -6,7 +6,7 @@ export type $Once = (eventName: string, callback: $OnceCallback) => number
export type $Off = (eventName: string, callback?: any | null) => void export type $Off = (eventName: string, callback?: any | null) => void
export type $Emit = (eventName: string, args: any | null) => void export type $Emit = (eventName: string, ...args: Array<any | null>) => void
export interface Uni { export interface Uni {
/** /**
...@@ -89,7 +89,7 @@ export interface Uni { ...@@ -89,7 +89,7 @@ export interface Uni {
/** /**
* 移除自定义事件监听器。如果提供了事件名和回调,则只移除这个回调的监听器。 * 移除自定义事件监听器。如果提供了事件名和回调,则只移除这个回调的监听器。
* 4.13+ 开始支持第二个参数为可选,如果仅提供事件名,则移除该事件的所有监听器。 * 4.13+ 开始支持第二个参数为可选,如果仅提供事件名,则移除该事件的所有监听器。
* 4.31+ 开始第二个参数的类型由 `Function \| null` 调整为 `any \| null`, 支持传入 `uni.$on`、`uni.$once` 返回的事件监听器 id, 移除指定事件监听器。 * 4.31+ 开始第二个参数的类型由 `Function | null` 调整为 `any | null`, 支持传入 `uni.$on`、`uni.$once` 返回的事件监听器 id, 移除指定事件监听器。
* @tutorial-uni-app-x https://doc.dcloud.net.cn/uni-app-x/api/event-bus.html#off * @tutorial-uni-app-x https://doc.dcloud.net.cn/uni-app-x/api/event-bus.html#off
* @tutorial https://doc.dcloud.net.cn/uni-app-x/api/event-bus.html#off * @tutorial https://doc.dcloud.net.cn/uni-app-x/api/event-bus.html#off
* @tutorial-uni-app https://uniapp.dcloud.net.cn/api/window/communication.html#off * @tutorial-uni-app https://uniapp.dcloud.net.cn/api/window/communication.html#off
...@@ -315,5 +315,5 @@ export interface Uni { ...@@ -315,5 +315,5 @@ export interface Uni {
* @param eventName 事件名称 * @param eventName 事件名称
* @param args 触发事件时传递的参数 * @param args 触发事件时传递的参数
*/ */
$emit(eventName: string, args: any | null): void $emit(eventName: string, ...args: Array<any | null>): void
} }
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
"app": { "app": {
"js": true, "js": true,
"kotlin": true, "kotlin": true,
"swift": false, "swift": true,
"arkts": true "arkts": true
} }
} }
......
import { ExitOptions, Exit} from "../interface.uts" import { ExitOptions, Exit, ExitSuccess} from "../interface.uts"
import { ExitFailImpl } from "../unierror.uts" import { ExitFailImpl} from "../unierror.uts"
import { UTSiOS } from "DCloudUTSFoundation";
/** /**
* 实现uni.exit * 实现uni.exit
* iOS平台不支持,触发错误回调
*/ */
export const exit : Exit = function (options: ExitOptions | null) { export const exit : Exit = function (options: ExitOptions | null) {
let err = new ExitFailImpl(12001);
options?.fail?.(err) const result = UTSiOS.exit();
options?.complete?.(err) if(result){
let ret : ExitSuccess ={
errMsg: "exit:ok"
}
options?.success?.(ret)
options?.complete?.(ret)
}else{
let error = new ExitFailImpl(12003);
options?.fail?.(error)
options?.complete?.(error)
}
} }
...@@ -16,7 +16,11 @@ export type ExitErrorCode = ...@@ -16,7 +16,11 @@ export type ExitErrorCode =
/** /**
* 未知错误 * 未知错误
*/ */
12002 12002 |
/**
* iOS平台,仅在uni-app x SDK模式中支持应用退出
*/
12003
/** /**
* uni.exit失败回调参数 * uni.exit失败回调参数
...@@ -62,33 +66,34 @@ export interface Uni { ...@@ -62,33 +66,34 @@ export interface Uni {
/** /**
* 退出当前应用 * 退出当前应用
* @uniPlatform { * @uniPlatform
* "app": { {
* "android": { "app": {
* "osVer": "5.0", "android": {
* "uniVer": "3.8.15", "osVer": "5.0",
* "uniUtsPlugin": "3.9.0", "uniVer": "3.8.15",
* "unixVer": "3.9.0", "uniUtsPlugin": "3.91",
* "unixUtsPlugin": "3.9.0" "unixVer": "3.91",
* }, "unixUtsPlugin": "3.91"
* "ios": { },
* "osVer": "x", "ios": {
* "uniVer": "x", "osVer": "x",
* "uniUtsPlugin": "x", "uniVer": "x",
* "unixVer": "x", "uniUtsPlugin": "x",
* "unixUtsPlugin": "x" "unixVer": "4.33",
* }, "unixUtsPlugin": "4.33"
* "harmony": { },
* "osVer": "3.0", "harmony": {
* "uniVer": "4.23", "osVer": "3.0",
* "unixVer": "x" "uniVer": "4.23",
* } "unixVer": "x"
* }, }
* "web": { },
* "uniVer": "x", "web": {
* "unixVer": "x" "uniVer": "x",
* } "unixVer": "x"
* } }
}
* @uniVueVersion 2,3 //支持的vue版本 * @uniVueVersion 2,3 //支持的vue版本
*/ */
exit(options?: ExitOptions | null):void; exit(options?: ExitOptions | null):void;
......
...@@ -11,6 +11,7 @@ export const ExitUniErrorSubject = 'uni-exit'; ...@@ -11,6 +11,7 @@ export const ExitUniErrorSubject = 'uni-exit';
* @UniError * @UniError
*/ */
export const ExitUniErrors:Map<number, string> = new Map([ export const ExitUniErrors:Map<number, string> = new Map([
/** /**
* 系统不支持 * 系统不支持
*/ */
...@@ -18,7 +19,11 @@ export const ExitUniErrors:Map<number, string> = new Map([ ...@@ -18,7 +19,11 @@ export const ExitUniErrors:Map<number, string> = new Map([
/** /**
* 未知错误 * 未知错误
*/ */
[12002, 'unknown error'] [12002, 'unknown error'],
/**
* iOS平台,仅在uni-app x SDK模式中支持应用退出
*/
[12003, 'app exit is supported only in uni-app x SDK mode']
]); ]);
/** /**
......
...@@ -194,7 +194,14 @@ export const getNetworkType: GetNetworkType = defineAsyncApi<GetNetworkTypeOptio ...@@ -194,7 +194,14 @@ export const getNetworkType: GetNetworkType = defineAsyncApi<GetNetworkTypeOptio
networkType: NetworkinfoType[type].toLocaleLowerCase() networkType: NetworkinfoType[type].toLocaleLowerCase()
} as GetNetworkTypeSuccess) } as GetNetworkTypeSuccess)
}).catch((err: BusinessError) => { }).catch((err: BusinessError) => {
res.reject(err.message) // NOTE 在 pad 上无网络
if (err.code === 2100001) {
res.resolve({
networkType: NetworkinfoType[1].toLocaleLowerCase()
} as GetNetworkTypeSuccess)
} else {
res.reject(err.message)
}
}) })
} }
) as GetNetworkType ) as GetNetworkType
......
...@@ -4,15 +4,17 @@ import AVRecorder, { supportFormats as avRecorderSupportFormats } from './AVReco ...@@ -4,15 +4,17 @@ import AVRecorder, { supportFormats as avRecorderSupportFormats } from './AVReco
import { onRecorderStateChange, setRecordStateCallback, StateChangeRes } from './utils.uts'; import { onRecorderStateChange, setRecordStateCallback, StateChangeRes } from './utils.uts';
// NOTE 避免被 vue Proxy 污染 // NOTE 避免被 vue Proxy 污染
let RECORDER_MANAGER: RecorderManager | null = null let RECORDER_MANAGER: AVRecorder | null = null
const DEFAULT_DURATION = 1000 * 60
const MAX_DURATION = DEFAULT_DURATION * 10
const DEFAULT_FORMAT = 'aac'
class RecorderManagerImpl implements RecorderManager { class RecorderManagerImpl implements RecorderManager {
start(options: RecorderManagerStartOptions): void { start(options: RecorderManagerStartOptions | null = null): void {
if (!options.format) options.format = 'aac' if (options == null) options = {} as RecorderManagerStartOptions
if (!options.format) options.format = DEFAULT_FORMAT
const DEFAULT_DURATION = 1000 * 60 if (options.duration == null) {
const MAX_DURATION = DEFAULT_DURATION * 10
if (typeof options.duration === 'undefined' || options.duration === null) {
options.duration = DEFAULT_DURATION options.duration = DEFAULT_DURATION
} }
if (options.duration > MAX_DURATION) { if (options.duration > MAX_DURATION) {
......
...@@ -111,11 +111,11 @@ function getWindowInfoResult() : GetWindowInfoResult { ...@@ -111,11 +111,11 @@ function getWindowInfoResult() : GetWindowInfoResult {
} }
const safeAreaLeft = insetLeft const safeAreaLeft = insetLeft
const safeAreaRight = windowWidth - insetRight const safeAreaRight = screenWidth - insetRight
const safeAreaTop = insetTop const safeAreaTop = insetTop
const safeAreaBottom = windowHeight - insetBottom const safeAreaBottom = screenHeight - insetBottom
const safeAreaWidth = windowWidth - insetLeft - insetRight const safeAreaWidth = screenWidth - insetLeft - insetRight
const safeAreaHeight = windowHeight - insetTop - insetBottom const safeAreaHeight = screenHeight - insetTop - insetBottom
const safeArea : SafeArea = { const safeArea : SafeArea = {
left: safeAreaLeft, left: safeAreaLeft,
......
...@@ -37,7 +37,7 @@ export const loadFontFace = defineAsyncApi< ...@@ -37,7 +37,7 @@ export const loadFontFace = defineAsyncApi<
} }
}) })
const SOURCE_REG = /(.+\.((ttf)|(otf)|(woff2?))$)|(^(http|https):\/\/.+)/ const SOURCE_REG = /(.+\.((ttf)|(otf)|(woff2?))$)|(^(http|https):\/\/.+)|(^(data:font).+)/
function checkOptionSource( function checkOptionSource(
options: LoadFontFaceOptions, options: LoadFontFaceOptions,
res: ApiExecutor, res: ApiExecutor,
...@@ -57,6 +57,11 @@ function checkOptionSource( ...@@ -57,6 +57,11 @@ function checkOptionSource(
function removeUrlWrap(source: string): string { function removeUrlWrap(source: string): string {
if (source.startsWith('url(')) { if (source.startsWith('url(')) {
// url("xxx") format("xxx") 时移除 format("xxx")
const FormatParts = source.split('format(')
if (FormatParts.length > 1) {
source = FormatParts[0].trim()
}
source = source.substring(4, source.length - 1) source = source.substring(4, source.length - 1)
} }
if (source.startsWith('"') || source.startsWith("'")) { if (source.startsWith('"') || source.startsWith("'")) {
......
...@@ -146,7 +146,8 @@ ...@@ -146,7 +146,8 @@
"dependencies": [ "dependencies": [
"uni-prompt", "uni-prompt",
"app-ios:permission-album", "app-ios:permission-album",
"app-ios:permission-camera" "app-ios:permission-camera",
"uni-framework"
], ],
"encrypt": [], "encrypt": [],
"platforms": { "platforms": {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
"dependencies": [ "dependencies": [
"com.github.bumptech.glide:glide:4.9.0", "com.github.bumptech.glide:glide:4.9.0",
"androidx.recyclerview:recyclerview:1.0.0", "androidx.recyclerview:recyclerview:1.0.0",
"androidx.appcompat:appcompat:1.0.0" "androidx.appcompat:appcompat:1.6.1",
"androidx.activity:activity-ktx:1.9.2"
] ]
} }
\ No newline at end of file
...@@ -11,14 +11,14 @@ import { ...@@ -11,14 +11,14 @@ import {
SaveVideoToPhotosAlbum, SaveVideoToPhotosAlbumOptions, SaveVideoToPhotosAlbumSuccess, SaveVideoToPhotosAlbum, SaveVideoToPhotosAlbumOptions, SaveVideoToPhotosAlbumSuccess,
CompressVideo, CompressVideoOptions, CompressVideo, CompressVideoOptions,
} from "../interface.uts" } from "../interface.uts"
export { ChooseFileSuccess, ChooseFileOptions, ChooseMediaFileType, ChooseMediaTempFile, ChooseMediaSuccess, ChooseMediaOptions, ChooseFileFail, ChooseFileComplete, ChooseMediaFail } from '../interface.uts'; export { ChooseFileSuccess, ChooseFileOptions, ChooseMediaFileType, ChooseMediaTempFile, ChooseMediaSuccess, ChooseMediaOptions, ChooseFileFail, ChooseFileComplete, ChooseMediaFail, LongPressActionsSuccessData, LongPressActionsOptions } from '../interface.uts';
import { import {
UniError_PreviewImage, UniError_GetImageInfo, UniError_SaveImageToPhotosAlbum, UniError_SaveVideoToPhotosAlbum, UniError_PreviewImage, UniError_GetImageInfo, UniError_SaveImageToPhotosAlbum, UniError_SaveVideoToPhotosAlbum,
MediaErrorImpl MediaErrorImpl
} from "../unierror.uts" } from "../unierror.uts"
import { chooseMediaImage, chooseMediaVideo } from "./utils/ChooseMediaUtils.uts" import { chooseMediaImage, chooseMediaVideo } from "./utils/ChooseMediaUtils.uts"
import { transcodeImage, transcodeVideo } from './utils/CompressUtils.uts' import { transcodeImage, transcodeVideo } from './utils/CompressUtils.uts'
import { getVideoMetadata, copyFile } from "./utils/MediaUtils.uts" import { getVideoMetadata, copyFile, getOrientation } from "./utils/MediaUtils.uts"
import Intent from 'android.content.Intent'; import Intent from 'android.content.Intent';
import Manifest from 'android.Manifest'; import Manifest from 'android.Manifest';
import Build from 'android.os.Build'; import Build from 'android.os.Build';
...@@ -118,18 +118,18 @@ class LongClick implements LongClickEventManager.OnLongClickListener { ...@@ -118,18 +118,18 @@ class LongClick implements LongClickEventManager.OnLongClickListener {
this.options = options this.options = options
} }
override onLongClickListener(values : JSONObject) { override onLongClickListener(values : JSONObject) {
var itemList : Array<string> | null = null // var itemList : Array<string> | null = null
var itemColor : string | null = null // var itemColor : string | null = null
var hasLongPressAction = false; // var hasLongPressAction = false;
if (this.options.longPressActions != null && this.options.longPressActions!.itemList != null && this.options.longPressActions!.itemList!.length > 0) { // if (this.options.longPressActions != null && this.options.longPressActions!.itemList != null && this.options.longPressActions!.itemList!.length > 0) {
itemList = this.options.longPressActions!.itemList! // itemList = this.options.longPressActions!.itemList!
hasLongPressAction = true // hasLongPressAction = true
} else { // } else {
itemList = ["保存"] // itemList = ["保存"]
} // }
if (this.options.longPressActions != null && this.options.longPressActions!.itemColor != null) { // if (this.options.longPressActions != null && this.options.longPressActions!.itemColor != null) {
itemColor = this.options.longPressActions!.itemColor! // itemColor = this.options.longPressActions!.itemColor!
} // }
// let actionOption : ShowActionSheetOptions = { // let actionOption : ShowActionSheetOptions = {
// "itemList": itemList!, // "itemList": itemList!,
// "itemColor": itemColor == null ? "" : itemColor!, // "itemColor": itemColor == null ? "" : itemColor!,
...@@ -259,7 +259,7 @@ class ImageInfoTarget extends CustomTarget<File> { ...@@ -259,7 +259,7 @@ class ImageInfoTarget extends CustomTarget<File> {
function getExif(src : string, options : GetImageInfoOptions, bitmapOption : BitmapFactory.Options | null) { function getExif(src : string, options : GetImageInfoOptions, bitmapOption : BitmapFactory.Options | null) {
var exifInfo : ExifInterface | null = null var exifInfo : ExifInterface | null = null
if(bitmapOption == null) { if (bitmapOption == null) {
bitmapOption = new BitmapFactory.Options(); bitmapOption = new BitmapFactory.Options();
bitmapOption.inJustDecodeBounds = true; bitmapOption.inJustDecodeBounds = true;
} }
...@@ -378,16 +378,16 @@ function loadFile(options : SaveImageToPhotosAlbumOptions, saveToAlbum : boolean ...@@ -378,16 +378,16 @@ function loadFile(options : SaveImageToPhotosAlbumOptions, saveToAlbum : boolean
} }
} }
function getInputStream(fromFilePath:string):InputStream|null { function getInputStream(fromFilePath : string) : InputStream | null {
var fis : InputStream | null = null var fis : InputStream | null = null
try { try {
if (fromFilePath.startsWith(ASSETS_PATH)) { if (fromFilePath.startsWith(ASSETS_PATH)) {
fis = UTSAndroid.getUniActivity()!.getAssets().open(fromFilePath.replace(ASSETS_PATH, "")); fis = UTSAndroid.getUniActivity()!.getAssets().open(fromFilePath.replace(ASSETS_PATH, ""));
} else { } else {
fis = new FileInputStream(fromFilePath) fis = new FileInputStream(fromFilePath)
} }
} catch(e){ } catch (e) {
} }
return fis return fis
} }
...@@ -409,6 +409,11 @@ function copyFileToPublicPath(fromFilePath : string, toFilePath : string, isVide ...@@ -409,6 +409,11 @@ function copyFileToPublicPath(fromFilePath : string, toFilePath : string, isVide
var mimeType : string | null = null var mimeType : string | null = null
if (isVideo) { if (isVideo) {
var retriever = new MediaMetadataRetriever() var retriever = new MediaMetadataRetriever()
if (fromFilePath.startsWith(ASSETS_PATH)) {
var mediaCachePath = UTSAndroid.getAppCachePath() + "uni-media/_" + System.currentTimeMillis()
copyFile(fromFilePath,mediaCachePath)
fromFilePath = mediaCachePath
}
retriever.setDataSource(fromFilePath) retriever.setDataSource(fromFilePath)
mimeType = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE); mimeType = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE);
} else { } else {
...@@ -445,7 +450,7 @@ function copyFileToPublicPath(fromFilePath : string, toFilePath : string, isVide ...@@ -445,7 +450,7 @@ function copyFileToPublicPath(fromFilePath : string, toFilePath : string, isVide
return false return false
} }
fis = getInputStream(fromFilePath) fis = getInputStream(fromFilePath)
if(fis == null) { if (fis == null) {
return false return false
} }
var byteArrays = ByteArray(102400 * 2) var byteArrays = ByteArray(102400 * 2)
...@@ -568,15 +573,10 @@ function loadFile(options : SaveVideoToPhotosAlbumOptions) { ...@@ -568,15 +573,10 @@ function loadFile(options : SaveVideoToPhotosAlbumOptions) {
options.complete?.(error) options.complete?.(error)
return return
} }
let originalPath = UTSAndroid.convert2AbsFullPath(options.filePath) var originalPath = options.filePath
if (originalPath.startsWith(ASSETS_PATH)) { var file = new File(originalPath)
originalPath = originalPath.replace(ASSETS_PATH, "") if (!file.exists()) {
} originalPath = UTSAndroid.convert2AbsFullPath(options.filePath)
if (!new File(originalPath).exists()) {
let error = new MediaErrorImpl(1101003, UniError_SaveVideoToPhotosAlbum);
options.fail?.(error)
options.complete?.(error)
return
} }
let path = DCIM_PATH + originalPath.substring(originalPath.lastIndexOf("/") + 1) let path = DCIM_PATH + originalPath.substring(originalPath.lastIndexOf("/") + 1)
if (copyFileToPublicPath(originalPath, path, true)) { if (copyFileToPublicPath(originalPath, path, true)) {
......
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromYDelta="100%p" />
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:toYDelta="100%p" />
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF" />
<stroke
android:width="3dp"
android:color="#ffffff" />
<corners android:radius="3dp" />
<padding
android:bottom="0dp"
android:left="0dp"
android:right="0dp"
android:top="0dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/uni_media_night_bg_main" />
<stroke
android:width="3dp"
android:color="@color/uni_media_night_bg_main" />
<corners android:radius="3dp" />
<padding
android:bottom="0dp"
android:left="0dp"
android:right="0dp"
android:top="0dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/uni_media_light_bg"
android:minWidth="500dp"
android:orientation="vertical">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/line_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/uni_media_dialog_bg_rounded"
android:orientation="vertical">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/line_title"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:gravity="center"
android:textColor="@color/uni_media_dialog_sub_text"
android:textSize="16sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/myRecyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/line_cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@color/uni_media_light_bg_main"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvCancelAction"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:text="@string/uni_media_cancel"
android:textColor="@color/uni_media_dialog_title_text"
android:textSize="20sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/line_bottom"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/uni_media_night_bg_hair_line"
android:orientation="vertical" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:gravity="center"
android:textColor="@color/uni_media_dialog_title_text"
android:foreground="?android:attr/selectableItemBackground"
android:textSize="20sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
\ No newline at end of file
<resources>
<string name="uni_media_placement">Configuration</string>
<string name="uni_media_cancel">取消</string>
</resources>
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册