diff --git a/demos/demo-android/app/build.gradle b/demos/demo-android/app/build.gradle index fb56f7147e..b099aa9117 100755 --- a/demos/demo-android/app/build.gradle +++ b/demos/demo-android/app/build.gradle @@ -73,7 +73,7 @@ dependencies { implementation 'com.jakewharton.timber:timber:5.0.1' implementation 'io.coil-kt:coil-compose:2.2.2' implementation "io.ktor:ktor-client-cio:2.1.3" - implementation "com.ricoh360.thetaclient:theta-client:1.5.0" + implementation "com.ricoh360.thetaclient:theta-client:1.6.0" testImplementation 'org.junit.jupiter:junit-jupiter:5.9.0' testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version" diff --git a/demos/demo-android/app/src/androidTest/java/com/ricoh360/thetaclient/thetaClientDemo/ExampleInstrumentedTest.kt b/demos/demo-android/app/src/androidTest/java/com/ricoh360/thetaclient/thetaClientDemo/ExampleInstrumentedTest.kt index 92ace3e30b..385c8dc34a 100755 --- a/demos/demo-android/app/src/androidTest/java/com/ricoh360/thetaclient/thetaClientDemo/ExampleInstrumentedTest.kt +++ b/demos/demo-android/app/src/androidTest/java/com/ricoh360/thetaclient/thetaClientDemo/ExampleInstrumentedTest.kt @@ -1,13 +1,11 @@ package com.ricoh360.thetaclient.thetaClientDemo -import androidx.test.platform.app.InstrumentationRegistry import androidx.test.ext.junit.runners.AndroidJUnit4 - +import androidx.test.platform.app.InstrumentationRegistry +import org.junit.Assert.* import org.junit.Test import org.junit.runner.RunWith -import org.junit.Assert.* - /** * Instrumented test, which will execute on an Android device. * diff --git a/demos/demo-android/app/src/main/assets/index.html b/demos/demo-android/app/src/main/assets/index.html index 337761a36d..cfc5758c5b 100755 --- a/demos/demo-android/app/src/main/assets/index.html +++ b/demos/demo-android/app/src/main/assets/index.html @@ -2,12 +2,12 @@ - + - - - + + - -

Preparing to display a photo.

-
- - - + +

Preparing to display a photo.

+
+ + + diff --git a/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/PhotoListScreen.kt b/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/PhotoListScreen.kt index 389bb7cb4e..5d952fd51d 100755 --- a/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/PhotoListScreen.kt +++ b/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/PhotoListScreen.kt @@ -1,13 +1,20 @@ package com.ricoh360.thetaclient.thetaClientDemo import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material.Scaffold import androidx.compose.material.Text import androidx.compose.material.TopAppBar -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.Dp @@ -26,7 +33,7 @@ fun PhotoListScreen( toPhoto: (fileName: String, photoUrl: String) -> Unit, viewModel: ThetaViewModel = androidx.lifecycle.viewmodel.compose.viewModel() ) { - val oscInfo : ThetaRepository.ThetaInfo? by viewModel.thetaInfoState.collectAsState(initial = null) + val oscInfo: ThetaRepository.ThetaInfo? by viewModel.thetaInfoState.collectAsState(initial = null) val thetaFiles: ThetaRepository.ThetaFiles? by viewModel.thetaFilesState.collectAsState(initial = null) ThetaSimpleAndroidAppTheme { @@ -40,9 +47,11 @@ fun PhotoListScreen( thetaFiles?.also { val thumbWidth = 100.dp val pad = 24.dp - LazyColumn(modifier = Modifier - .fillMaxSize() - .padding(pad)) { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(pad) + ) { items(it.fileList) { file -> Row(horizontalArrangement = Arrangement.Center) { ThumbnailImage( diff --git a/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/PhotoScreen.kt b/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/PhotoScreen.kt index 5503f2011b..3844c74d38 100755 --- a/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/PhotoScreen.kt +++ b/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/PhotoScreen.kt @@ -3,7 +3,7 @@ package com.ricoh360.thetaclient.thetaClientDemo import androidx.compose.material.Scaffold import androidx.compose.material.Text import androidx.compose.material.TopAppBar -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable import com.ricoh360.thetaclient.thetaClientDemo.ui.theme.ThetaSimpleAndroidAppTheme import timber.log.Timber @@ -19,7 +19,7 @@ fun PhotoScreen(fileName: String?, photoUrl: String?) { ThetaSimpleAndroidAppTheme { Scaffold( topBar = { - TopAppBar(title = { Text(fileName?: "") }) + TopAppBar(title = { Text(fileName ?: "") }) } ) { photoUrl?.let { diff --git a/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/PreviewScreen.kt b/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/PreviewScreen.kt index cc9d97d94e..d7a4e420ab 100755 --- a/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/PreviewScreen.kt +++ b/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/PreviewScreen.kt @@ -7,7 +7,10 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.FabPosition import androidx.compose.material.FloatingActionButton import androidx.compose.material.Scaffold -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.asImageBitmap @@ -16,7 +19,10 @@ import androidx.compose.ui.platform.LocalLifecycleOwner import com.ricoh360.thetaclient.ThetaRepository import com.ricoh360.thetaclient.capture.PhotoCapture import com.ricoh360.thetaclient.thetaClientDemo.ui.theme.ThetaSimpleAndroidAppTheme -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch import timber.log.Timber /** diff --git a/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/ThetaViewModel.kt b/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/ThetaViewModel.kt index 0dcbc04fe8..6dddd1078c 100755 --- a/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/ThetaViewModel.kt +++ b/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/ThetaViewModel.kt @@ -4,7 +4,6 @@ import android.graphics.Bitmap import android.graphics.BitmapFactory import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.ricoh360.thetaclient.DigestAuth import com.ricoh360.thetaclient.ThetaRepository import com.ricoh360.thetaclient.capture.PhotoCapture import io.ktor.client.utils.* @@ -26,10 +25,10 @@ class ThetaViewModel( private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO, ) : ViewModel() { private var thetaRepository: ThetaRepository - private val _thetaInfoState = MutableStateFlow(null) + private val _thetaInfoState = MutableStateFlow(null) val thetaInfoState: StateFlow = _thetaInfoState private val _thetaFilesState = MutableStateFlow(null) - val thetaFilesState: StateFlow = _thetaFilesState + val thetaFilesState: StateFlow = _thetaFilesState private val _previewFlow = MutableStateFlow(null) val previewFlow: StateFlow = _previewFlow @@ -97,7 +96,7 @@ class ThetaViewModel( previewJob = viewModelScope.launch(ioDispatcher) { runCatching { thetaRepository.getLivePreview { frame: Pair -> - if(!isActive) { + if (!isActive) { Timber.d("Terminate preview") return@getLivePreview false } @@ -112,7 +111,7 @@ class ThetaViewModel( } } - fun stopPreview () { + fun stopPreview() { previewJob?.let { it.cancel() previewJob = null diff --git a/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/Viewer360.kt b/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/Viewer360.kt index 8e3f38a9e2..f74d2bd2f3 100755 --- a/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/Viewer360.kt +++ b/demos/demo-android/app/src/main/java/com/ricoh360/thetaclient/thetaClientDemo/Viewer360.kt @@ -4,25 +4,33 @@ import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Matrix import android.view.ViewGroup -import android.webkit.* +import android.webkit.JavascriptInterface +import android.webkit.WebResourceRequest +import android.webkit.WebResourceResponse +import android.webkit.WebSettings +import android.webkit.WebView import androidx.compose.foundation.layout.fillMaxSize -import androidx.webkit.WebViewClientCompat -import androidx.webkit.WebViewAssetLoader -import androidx.webkit.WebResourceErrorCompat -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.viewinterop.AndroidView - -import io.ktor.client.* -import io.ktor.client.call.* -import io.ktor.client.engine.cio.* -import io.ktor.client.request.* -import io.ktor.http.* +import androidx.webkit.WebResourceErrorCompat +import androidx.webkit.WebViewAssetLoader +import androidx.webkit.WebViewClientCompat +import io.ktor.client.HttpClient +import io.ktor.client.call.body +import io.ktor.client.engine.cio.CIO +import io.ktor.client.request.get +import io.ktor.http.isSuccess import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import timber.log.Timber import java.io.ByteArrayOutputStream -import java.util.* +import java.util.Base64 /** * Viewer for equirectangular image @@ -70,7 +78,7 @@ fun Viewer360Core(photoDataUrl: String) { /** * Injecting object to WebView's JavaScript. */ - class JsObject() { + class JsObject { @JavascriptInterface fun getPhotoUrl(): String { Timber.d("called getPhotoUrl(): ${photoDataUrl.substring(0, 40)}...") @@ -125,7 +133,7 @@ fun Viewer360Core(photoDataUrl: String) { WebView(context).apply { settings.allowFileAccess = true settings.javaScriptEnabled = true - settings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE) + settings.mixedContentMode = WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE addJavascriptInterface(JsObject(), "injectedObject") webViewClient = LocalContentWebViewClient(assetLoader) layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) @@ -164,7 +172,7 @@ suspend fun getPhotoDataUrl(photoUrl: String): String? = withContext(Dispatchers var dataUrl: String? = null HttpClient(CIO).use { httpClient -> val response = httpClient.get(photoUrl) - if(response.status.isSuccess()) { + if (response.status.isSuccess()) { val byteArray: ByteArray = response.body() dataUrl = DATA_URL_PREFIX + Base64.getEncoder().encodeToString(downSizeImage(byteArray)) } else { @@ -201,7 +209,7 @@ fun downSizeImage(image: ByteArray): ByteArray { } BitmapFactory.decodeByteArray(image, 0, image.size, options) Timber.d("Jpeg width; ${options.outWidth}") - if(options.outWidth > MAX_WIDTH) { + if (options.outWidth > MAX_WIDTH) { val scaleFactor = MAX_WIDTH / options.outWidth.toFloat() val scale = Matrix() scale.postScale(scaleFactor, scaleFactor) diff --git a/demos/demo-android/app/src/test/java/com/ricoh360/thetaclient/thetaClientDemo/ThetaViewModelTest.kt b/demos/demo-android/app/src/test/java/com/ricoh360/thetaclient/thetaClientDemo/ThetaViewModelTest.kt index 78cc7a8d54..387f564fa2 100755 --- a/demos/demo-android/app/src/test/java/com/ricoh360/thetaclient/thetaClientDemo/ThetaViewModelTest.kt +++ b/demos/demo-android/app/src/test/java/com/ricoh360/thetaclient/thetaClientDemo/ThetaViewModelTest.kt @@ -2,7 +2,6 @@ package com.ricoh360.thetaclient.thetaClientDemo import com.ricoh360.thetaclient.ThetaRepository import com.ricoh360.thetaclient.capture.PhotoCapture -import com.ricoh360.thetaclient.thetaClientDemo.ThetaViewModel import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.runTest @@ -34,15 +33,15 @@ internal class ThetaViewModelTest { assertNotNull(files, "thetaFilesState") } - /* - @Test - @kotlinx.coroutines.ExperimentalCoroutinesApi - fun previewTest() = runTest { - vm.startPreview() - val bitmap = vm.previewFlow.drop(1).first() - assertNotNull(bitmap, "preview") - vm.stopPreview() - } */ + /* + @Test + @kotlinx.coroutines.ExperimentalCoroutinesApi + fun previewTest() = runTest { + vm.startPreview() + val bitmap = vm.previewFlow.drop(1).first() + assertNotNull(bitmap, "preview") + vm.stopPreview() + } */ @Test fun shootingTest() = runTest { diff --git a/demos/demo-flutter/ios/Runner/AppDelegate.swift b/demos/demo-flutter/ios/Runner/AppDelegate.swift index 70693e4a8c..1756297092 100644 --- a/demos/demo-flutter/ios/Runner/AppDelegate.swift +++ b/demos/demo-flutter/ios/Runner/AppDelegate.swift @@ -1,13 +1,13 @@ -import UIKit import Flutter +import UIKit @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } } diff --git a/demos/demo-flutter/lib/capture_video_screen.dart b/demos/demo-flutter/lib/capture_video_screen.dart index a18b61845b..a549592689 100644 --- a/demos/demo-flutter/lib/capture_video_screen.dart +++ b/demos/demo-flutter/lib/capture_video_screen.dart @@ -14,7 +14,8 @@ class CaptureVideoScreen extends StatefulWidget { } } -class _CaptureVideoScreen extends State with WidgetsBindingObserver { +class _CaptureVideoScreen extends State + with WidgetsBindingObserver { final _thetaClientFlutter = ThetaClientFlutter(); Uint8List frameData = Uint8List(0); @@ -30,6 +31,7 @@ class _CaptureVideoScreen extends State with WidgetsBindingO WidgetsBinding.instance.addObserver(this); initialize(); } + @override void deactivate() { WidgetsBinding.instance.removeObserver(this); @@ -42,10 +44,10 @@ class _CaptureVideoScreen extends State with WidgetsBindingO void didChangeAppLifecycleState(AppLifecycleState state) { switch (state) { case AppLifecycleState.resumed: - onResume(); + onResume(); break; case AppLifecycleState.paused: - onPause(); + onPause(); break; default: break; @@ -54,12 +56,11 @@ class _CaptureVideoScreen extends State with WidgetsBindingO void onResume() { debugPrint('onResume'); - _thetaClientFlutter.isInitialized() - .then((isInit) { - if (isInit) { - startLivePreview(); - } - }); + _thetaClientFlutter.isInitialized().then((isInit) { + if (isInit) { + startLivePreview(); + } + }); } void onPause() { @@ -70,40 +71,35 @@ class _CaptureVideoScreen extends State with WidgetsBindingO @override Widget build(BuildContext context) { return WillPopScope( - child: Scaffold( - appBar: AppBar( - title: const Text('Capture Video') - ), - body: Stack( - fit: StackFit.expand, - children: [ - Container( + child: Scaffold( + appBar: AppBar(title: const Text('Capture Video')), + body: Stack( + fit: StackFit.expand, + children: [ + Container( color: Colors.black, child: Center( - child: - shooting ? const Text( - 'Capturing...', - style: TextStyle( - fontSize: 20, - color: Colors.white, - ), - ): - Image.memory( - frameData, - errorBuilder: (a, b, c) { - return Container( - color: Colors.black, - ); - }, - gaplessPlayback: true, - ) - , - ) - ), - Container( + child: shooting + ? const Text( + 'Capturing...', + style: TextStyle( + fontSize: 20, + color: Colors.white, + ), + ) + : Image.memory( + frameData, + errorBuilder: (a, b, c) { + return Container( + color: Colors.black, + ); + }, + gaplessPlayback: true, + ), + )), + Container( alignment: const Alignment(0, 0.8), - child: - MaterialButton( + child: MaterialButton( height: 80, shape: const CircleBorder(), color: shooting ? Colors.white : Colors.red, @@ -114,13 +110,12 @@ class _CaptureVideoScreen extends State with WidgetsBindingO } startVideoCapture(); }, - ) - ), - ], - ), + )), + ], ), - onWillPop: () => backButtonPress(context), - ); + ), + onWillPop: () => backButtonPress(context), + ); } Future backButtonPress(BuildContext context) async { @@ -133,20 +128,18 @@ class _CaptureVideoScreen extends State with WidgetsBindingO debugPrint('init CaptureVideo'); // initialize VideoCapture builder = _thetaClientFlutter.getVideoCaptureBuilder(); - builder!.build() - .then((value) { - videoCapture = value; - debugPrint('Ready VideoCapture'); - Future.delayed(const Duration(milliseconds: 500), (){}).then((value) { - // Wait because it can fail. - startLivePreview(); - }); - }) - .onError((error, stackTrace) { - MessageBox.show(context, 'Error VideoCaptureBuilder', () { - backScreen(); - }); + builder!.build().then((value) { + videoCapture = value; + debugPrint('Ready VideoCapture'); + Future.delayed(const Duration(milliseconds: 500), () {}).then((value) { + // Wait because it can fail. + startLivePreview(); + }); + }).onError((error, stackTrace) { + MessageBox.show(context, 'Error VideoCaptureBuilder', () { + backScreen(); }); + }); debugPrint('initializing...'); } @@ -161,16 +154,14 @@ class _CaptureVideoScreen extends State with WidgetsBindingO void startLivePreview() { previewing = true; - _thetaClientFlutter.getLivePreview(frameHandler) - .then((value) { - debugPrint('LivePreview end.'); - }) - .onError((error, stackTrace) { - debugPrint('Error getLivePreview.'); - MessageBox.show(context, 'Error getLivePreview', () { - backScreen(); - }); + _thetaClientFlutter.getLivePreview(frameHandler).then((value) { + debugPrint('LivePreview end.'); + }).onError((error, stackTrace) { + debugPrint('Error getLivePreview.'); + MessageBox.show(context, 'Error getLivePreview', () { + backScreen(); }); + }); debugPrint('LivePreview starting..'); } @@ -188,7 +179,7 @@ class _CaptureVideoScreen extends State with WidgetsBindingO return; } if (shooting) { - debugPrint('already shooting'); + debugPrint('already shooting'); return; } setState(() { @@ -198,7 +189,6 @@ class _CaptureVideoScreen extends State with WidgetsBindingO // Stops while shooting is in progress stopLivePreview(); - videoCapturing = videoCapture?.startCapture((fileUrl) { setState(() { shooting = false; @@ -208,13 +198,13 @@ class _CaptureVideoScreen extends State with WidgetsBindingO if (fileUrl != null) { final uri = Uri.parse(fileUrl); - Navigator.of(context).push( - MaterialPageRoute(builder: (_) => VideoScreen( - name: uri.pathSegments.last, - fileUrl: fileUrl, - ) - ) - ).then((value) => startLivePreview()); + Navigator.of(context) + .push(MaterialPageRoute( + builder: (_) => VideoScreen( + name: uri.pathSegments.last, + fileUrl: fileUrl, + ))) + .then((value) => startLivePreview()); } }, (exception) { setState(() { @@ -222,7 +212,6 @@ class _CaptureVideoScreen extends State with WidgetsBindingO }); startLivePreview(); debugPrint(exception.toString()); - }, onStopFailed: (exception) { debugPrint(exception.toString()); MessageBox.show(context, 'Error. stopCapture.\n$exception'); @@ -231,7 +220,7 @@ class _CaptureVideoScreen extends State with WidgetsBindingO void stopVideoCapture() { if (!shooting || videoCapturing == null) { - debugPrint('Not start capture.'); + debugPrint('Not start capture.'); return; } debugPrint("stopVideoCapture"); diff --git a/demos/demo-flutter/lib/file_list_screen.dart b/demos/demo-flutter/lib/file_list_screen.dart index f13710190e..a46fb0e132 100644 --- a/demos/demo-flutter/lib/file_list_screen.dart +++ b/demos/demo-flutter/lib/file_list_screen.dart @@ -8,12 +8,11 @@ import 'message_box.dart'; class FileListScreen extends StatefulWidget { const FileListScreen({Key? key}) : super(key: key); - + @override State createState() { return _FileListScreen(); } - } class _FileListScreen extends State { @@ -51,54 +50,46 @@ class _FileListScreen extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('File List') - ), - body: ListView.builder( - itemCount: _fileInfoList.length, - itemBuilder: (context, index) { - return ListTile( - title: Text(_fileInfoList[index].name), - onTap: () { - debugPrint('index $index'); - final fileUrl = _fileInfoList[index].fileUrl; - // fileUrl.endsWith('.MP4')/ - Navigator.of(context).push( - MaterialPageRoute(builder: (_) => - fileUrl.endsWith('.MP4') ? - VideoScreen( - name: _fileInfoList[index].name, - fileUrl: fileUrl, - ) : - PhotoScreen( - name: _fileInfoList[index].name, - fileUrl: fileUrl, - ) - ) - ); - }, - leading: Image.network( - _fileInfoList[index].thumbnailUrl, - width: 128, - loadingBuilder: (context, child, loadingProgress) { - if (loadingProgress == null) return child; - return Container( - width: 128, - color: Colors.white, - child: const Text('loading...') - ); - }, - errorBuilder: (a, b, c) { - return Container( - width: 128, - color: Colors.white, - child: const Text('Error') - ); + appBar: AppBar(title: const Text('File List')), + body: ListView.builder( + itemCount: _fileInfoList.length, + itemBuilder: (context, index) { + return ListTile( + title: Text(_fileInfoList[index].name), + onTap: () { + debugPrint('index $index'); + final fileUrl = _fileInfoList[index].fileUrl; + // fileUrl.endsWith('.MP4')/ + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => fileUrl.endsWith('.MP4') + ? VideoScreen( + name: _fileInfoList[index].name, + fileUrl: fileUrl, + ) + : PhotoScreen( + name: _fileInfoList[index].name, + fileUrl: fileUrl, + ))); }, - ), - ); - }, - ) - ); + leading: Image.network( + _fileInfoList[index].thumbnailUrl, + width: 128, + loadingBuilder: (context, child, loadingProgress) { + if (loadingProgress == null) return child; + return Container( + width: 128, + color: Colors.white, + child: const Text('loading...')); + }, + errorBuilder: (a, b, c) { + return Container( + width: 128, + color: Colors.white, + child: const Text('Error')); + }, + ), + ); + }, + )); } } diff --git a/demos/demo-flutter/lib/main.dart b/demos/demo-flutter/lib/main.dart index 0cbdcf4c82..0bb05a0ea2 100644 --- a/demos/demo-flutter/lib/main.dart +++ b/demos/demo-flutter/lib/main.dart @@ -1,12 +1,11 @@ +import 'dart:async'; + import 'package:demo_flutter/capture_video_screen.dart'; import 'package:demo_flutter/file_list_screen.dart'; import 'package:demo_flutter/message_box.dart'; import 'package:demo_flutter/take_picture_screen.dart'; import 'package:flutter/material.dart'; -import 'dart:async'; - import 'package:flutter/services.dart'; -import 'package:theta_client_flutter/digest_auth.dart'; import 'package:theta_client_flutter/theta_client_flutter.dart'; void main() { @@ -59,8 +58,8 @@ class _MyAppState extends State with WidgetsBindingObserver { Future initPlatformState() async { String platformVersion; try { - platformVersion = - await _thetaClientFlutter.getPlatformVersion() ?? 'Unknown platform version'; + platformVersion = await _thetaClientFlutter.getPlatformVersion() ?? + 'Unknown platform version'; } on PlatformException { platformVersion = 'Failed to get platform version.'; } @@ -127,17 +126,18 @@ class Home extends StatelessWidget { final bool isInitialized; final Function connectTheta; final ThetaModel? thetaModel; - const Home({Key? key, + + const Home({ + Key? key, required this.platformVersion, required this.isInitialized, required this.connectTheta, required this.thetaModel, - }) : super(key: key); - + }) : super(key: key); @override Widget build(BuildContext context) { - String camera = isInitialized ? 'connected! $thetaModel': 'disconnected'; + String camera = isInitialized ? 'connected! $thetaModel' : 'disconnected'; return Scaffold( appBar: AppBar( title: const Text('Plugin example app'), @@ -150,43 +150,43 @@ class Home extends StatelessWidget { Text('Running on: $platformVersion\n'), Text('Camera: $camera\n'), TextButton( - onPressed: isInitialized ? null: () { - connectTheta(); - }, + onPressed: isInitialized + ? null + : () { + connectTheta(); + }, child: const Text('Connect'), - ), TextButton( - onPressed: !isInitialized ? null: () { - Navigator.of(context).push( - MaterialPageRoute(builder: (_) => const TakePictureScreen()) - ); - }, + onPressed: !isInitialized + ? null + : () { + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => const TakePictureScreen())); + }, child: const Text('Take Picture'), - ), TextButton( - onPressed: !isInitialized ? null: () { - Navigator.of(context).push( - MaterialPageRoute(builder: (_) => const CaptureVideoScreen()) - ); - }, + onPressed: !isInitialized + ? null + : () { + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => const CaptureVideoScreen())); + }, child: const Text('Capture Video'), - ), TextButton( - onPressed: !isInitialized ? null: () { - Navigator.of(context).push( - MaterialPageRoute(builder: (_) => const FileListScreen()) - ); - }, + onPressed: !isInitialized + ? null + : () { + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => const FileListScreen())); + }, child: const Text('File List'), - ), ], ), ), - ) - ); + )); } } diff --git a/demos/demo-flutter/lib/message_box.dart b/demos/demo-flutter/lib/message_box.dart index 07d1a4854f..efc737176b 100644 --- a/demos/demo-flutter/lib/message_box.dart +++ b/demos/demo-flutter/lib/message_box.dart @@ -3,10 +3,9 @@ import 'package:flutter/material.dart'; class MessageBox extends StatelessWidget { final String title; final Function? onClose; - const MessageBox({Key? key, - required this.title, - this.onClose - }) : super(key: key); + + const MessageBox({Key? key, required this.title, this.onClose}) + : super(key: key); @override Widget build(BuildContext context) { @@ -14,24 +13,25 @@ class MessageBox extends StatelessWidget { title: Text(title), actions: [ ElevatedButton( - onPressed: () { - Navigator.pop(context); - if (onClose != null) { - onClose!(); - } - }, - child: const Text('OK') - ), + onPressed: () { + Navigator.pop(context); + if (onClose != null) { + onClose!(); + } + }, + child: const Text('OK')), ], ); } static void show(BuildContext context, String title, [Function? onClose]) { showDialog( - context: context, - builder: (context) { - return MessageBox(title: title, onClose: onClose,); - } - ); + context: context, + builder: (context) { + return MessageBox( + title: title, + onClose: onClose, + ); + }); } } diff --git a/demos/demo-flutter/lib/photo_screen.dart b/demos/demo-flutter/lib/photo_screen.dart index 9e87c442fd..52a49682f0 100644 --- a/demos/demo-flutter/lib/photo_screen.dart +++ b/demos/demo-flutter/lib/photo_screen.dart @@ -3,7 +3,9 @@ import 'package:flutter/material.dart'; class PhotoScreen extends StatelessWidget { final String name; final String fileUrl; - const PhotoScreen({Key? key, + + const PhotoScreen({ + Key? key, required this.name, required this.fileUrl, }) : super(key: key); @@ -11,25 +13,20 @@ class PhotoScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: Text('Photo: $name') - ), - body: Container( - alignment: Alignment.center, - child: Image.network( - fileUrl, - loadingBuilder: (context, child, loadingProgress) { - if (loadingProgress == null) return child; - return const Text('loading...'); - }, - errorBuilder: (a, b, c) { - return Container( - color: Colors.white, - ); - }, - ) - ) - ); + appBar: AppBar(title: Text('Photo: $name')), + body: Container( + alignment: Alignment.center, + child: Image.network( + fileUrl, + loadingBuilder: (context, child, loadingProgress) { + if (loadingProgress == null) return child; + return const Text('loading...'); + }, + errorBuilder: (a, b, c) { + return Container( + color: Colors.white, + ); + }, + ))); } - -} \ No newline at end of file +} diff --git a/demos/demo-flutter/lib/take_picture_screen.dart b/demos/demo-flutter/lib/take_picture_screen.dart index 4a6e7c70fe..f9c04dfe40 100644 --- a/demos/demo-flutter/lib/take_picture_screen.dart +++ b/demos/demo-flutter/lib/take_picture_screen.dart @@ -13,7 +13,8 @@ class TakePictureScreen extends StatefulWidget { } } -class _TakePictureScreen extends State with WidgetsBindingObserver { +class _TakePictureScreen extends State + with WidgetsBindingObserver { final _thetaClientFlutter = ThetaClientFlutter(); Uint8List frameData = Uint8List(0); @@ -28,6 +29,7 @@ class _TakePictureScreen extends State with WidgetsBindingObs WidgetsBinding.instance.addObserver(this); initialize(); } + @override void deactivate() { WidgetsBinding.instance.removeObserver(this); @@ -40,10 +42,10 @@ class _TakePictureScreen extends State with WidgetsBindingObs void didChangeAppLifecycleState(AppLifecycleState state) { switch (state) { case AppLifecycleState.resumed: - onResume(); + onResume(); break; case AppLifecycleState.paused: - onPause(); + onPause(); break; default: break; @@ -52,12 +54,11 @@ class _TakePictureScreen extends State with WidgetsBindingObs void onResume() { debugPrint('onResume'); - _thetaClientFlutter.isInitialized() - .then((isInit) { - if (isInit) { - startLivePreview(); - } - }); + _thetaClientFlutter.isInitialized().then((isInit) { + if (isInit) { + startLivePreview(); + } + }); } void onPause() { @@ -68,39 +69,35 @@ class _TakePictureScreen extends State with WidgetsBindingObs @override Widget build(BuildContext context) { return WillPopScope( - child: Scaffold( - appBar: AppBar( - title: const Text('Take Picture') - ), - body: Stack( - fit: StackFit.expand, - children: [ - Container( + child: Scaffold( + appBar: AppBar(title: const Text('Take Picture')), + body: Stack( + fit: StackFit.expand, + children: [ + Container( color: Colors.black, child: Center( - child: - shooting ? const Text( - 'Take Picture...', - style: TextStyle( - fontSize: 20, - color: Colors.white, - ), - ): - Image.memory( - frameData, - errorBuilder: (a, b, c) { - return Container( - color: Colors.black, - ); - }, - gaplessPlayback: true, - ), - ) - ), - Container( + child: shooting + ? const Text( + 'Take Picture...', + style: TextStyle( + fontSize: 20, + color: Colors.white, + ), + ) + : Image.memory( + frameData, + errorBuilder: (a, b, c) { + return Container( + color: Colors.black, + ); + }, + gaplessPlayback: true, + ), + )), + Container( alignment: const Alignment(0, 0.8), - child: - MaterialButton( + child: MaterialButton( height: 80, shape: const CircleBorder(), color: Colors.white, @@ -111,13 +108,12 @@ class _TakePictureScreen extends State with WidgetsBindingObs } takePicture(); }, - ) - ), - ], - ), + )), + ], ), - onWillPop: () => backButtonPress(context), - ); + ), + onWillPop: () => backButtonPress(context), + ); } Future backButtonPress(BuildContext context) async { @@ -130,20 +126,18 @@ class _TakePictureScreen extends State with WidgetsBindingObs debugPrint('init TakePicture'); // initialize PhotoCapture builder = _thetaClientFlutter.getPhotoCaptureBuilder(); - builder!.build() - .then((value) { - photoCapture = value; - debugPrint('Ready PhotoCapture'); - Future.delayed(const Duration(milliseconds: 500), (){}).then((value) { - // Wait because it can fail. - startLivePreview(); - }); - }) - .onError((error, stackTrace) { - MessageBox.show(context, 'Error PhotoCaptureBuilder', () { - backScreen(); - }); + builder!.build().then((value) { + photoCapture = value; + debugPrint('Ready PhotoCapture'); + Future.delayed(const Duration(milliseconds: 500), () {}).then((value) { + // Wait because it can fail. + startLivePreview(); + }); + }).onError((error, stackTrace) { + MessageBox.show(context, 'Error PhotoCaptureBuilder', () { + backScreen(); }); + }); debugPrint('initializing...'); } @@ -158,16 +152,14 @@ class _TakePictureScreen extends State with WidgetsBindingObs void startLivePreview() { previewing = true; - _thetaClientFlutter.getLivePreview(frameHandler) - .then((value) { - debugPrint('LivePreview end.'); - }) - .onError((error, stackTrace) { - debugPrint('Error getLivePreview.$error'); - MessageBox.show(context, 'Error getLivePreview', () { - backScreen(); - }); + _thetaClientFlutter.getLivePreview(frameHandler).then((value) { + debugPrint('LivePreview end.'); + }).onError((error, stackTrace) { + debugPrint('Error getLivePreview.$error'); + MessageBox.show(context, 'Error getLivePreview', () { + backScreen(); }); + }); debugPrint('LivePreview starting..'); } @@ -182,7 +174,7 @@ class _TakePictureScreen extends State with WidgetsBindingObs void takePicture() { if (shooting) { - debugPrint('already shooting'); + debugPrint('already shooting'); return; } setState(() { @@ -199,13 +191,13 @@ class _TakePictureScreen extends State with WidgetsBindingObs debugPrint('take picture: $fileUrl'); if (!mounted) return; if (fileUrl != null) { - Navigator.of(context).push( - MaterialPageRoute(builder: (_) => PhotoScreen( - name: 'Take Picture', - fileUrl: fileUrl, - ) - ) - ).then((value) => startLivePreview()); + Navigator.of(context) + .push(MaterialPageRoute( + builder: (_) => PhotoScreen( + name: 'Take Picture', + fileUrl: fileUrl, + ))) + .then((value) => startLivePreview()); } else { setState(() { shooting = true; diff --git a/demos/demo-flutter/lib/video_screen.dart b/demos/demo-flutter/lib/video_screen.dart index 80e6340eec..60a0b969ab 100644 --- a/demos/demo-flutter/lib/video_screen.dart +++ b/demos/demo-flutter/lib/video_screen.dart @@ -4,7 +4,9 @@ import 'package:video_player/video_player.dart'; class VideoScreen extends StatefulWidget { final String name; final String fileUrl; - const VideoScreen({Key? key, + + const VideoScreen({ + Key? key, required this.name, required this.fileUrl, }) : super(key: key); @@ -30,9 +32,7 @@ class _VideoScreen extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: Text('Video: ${widget.name}') - ), + appBar: AppBar(title: Text('Video: ${widget.name}')), body: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -46,8 +46,8 @@ class _VideoScreen extends State { IconButton( onPressed: () { _controller - .seekTo(Duration.zero) - .then((_) => _controller.play()); + .seekTo(Duration.zero) + .then((_) => _controller.play()); }, icon: const Icon(Icons.refresh), ), diff --git a/demos/demo-flutter/test/widget_test.dart b/demos/demo-flutter/test/widget_test.dart index 929c56655f..2aaa83c3da 100644 --- a/demos/demo-flutter/test/widget_test.dart +++ b/demos/demo-flutter/test/widget_test.dart @@ -5,11 +5,10 @@ // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. +import 'package:demo_flutter/main.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:demo_flutter/main.dart'; - void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. diff --git a/demos/demo-ios/Podfile b/demos/demo-ios/Podfile index 678f254fdf..1db0c3379e 100644 --- a/demos/demo-ios/Podfile +++ b/demos/demo-ios/Podfile @@ -7,5 +7,5 @@ target 'SdkSample' do use_frameworks! # Pods for SdkSample - pod 'THETAClient', '1.5.0' + pod 'THETAClient', '1.6.0' end diff --git a/demos/demo-ios/SdkSample/ContentView.swift b/demos/demo-ios/SdkSample/ContentView.swift index fb6b148828..ad03b793b2 100644 --- a/demos/demo-ios/SdkSample/ContentView.swift +++ b/demos/demo-ios/SdkSample/ContentView.swift @@ -4,7 +4,7 @@ // import SwiftUI -let purple_700: UIColor = UIColor(hex: "6200EE") +let purple_700: UIColor = .init(hex: "6200EE") struct ContentView: View { @State var getInfoError: Bool = false @@ -19,31 +19,31 @@ struct ContentView: View { UINavigationBar.appearance().standardAppearance = appearance UINavigationBar.appearance().scrollEdgeAppearance = appearance } + var body: some View { NavigationView { VStack(spacing: 16) { NavigationLink(destination: TakePhotoView()) { Text("Take a photo") } - .padding(12) - .accentColor(Color.white) - .background(Color(purple_700)) - .cornerRadius(10) + .padding(12) + .accentColor(Color.white) + .background(Color(purple_700)) + .cornerRadius(10) NavigationLink(destination: ListPhotosView()) { Text("List photos") } - .padding(12) - .accentColor(Color.white) - .background(Color(purple_700)) - .cornerRadius(10) + .padding(12) + .accentColor(Color.white) + .background(Color(purple_700)) + .cornerRadius(10) + } + .navigationTitle("Theta SDK sample app") + .navigationBarTitleDisplayMode(.inline) + .alert("warning", isPresented: $getInfoError) {} message: { + Text("Can not connect to Theta.") } - .navigationTitle("Theta SDK sample app") - .navigationBarTitleDisplayMode(.inline) - .alert("warning", isPresented: $getInfoError) { - } message: { - Text("Can not connect to Theta.") - } } .onChange(of: scenePhase) { newPhase in if newPhase == .active { @@ -51,7 +51,7 @@ struct ContentView: View { theta.reset() Task { do { - try await theta.info {info in + try await theta.info { info in print(info) } } catch { @@ -60,7 +60,6 @@ struct ContentView: View { } } } - } } diff --git a/demos/demo-ios/SdkSample/ListPhotosView.swift b/demos/demo-ios/SdkSample/ListPhotosView.swift index d1e5682f54..fd2da23f1f 100644 --- a/demos/demo-ios/SdkSample/ListPhotosView.swift +++ b/demos/demo-ios/SdkSample/ListPhotosView.swift @@ -4,7 +4,7 @@ // import SwiftUI -class FileItem:Identifiable { +class FileItem: Identifiable { var name: String var url: String var thumbnail: String @@ -20,28 +20,28 @@ struct ListPhotosView: View { @State var files: [FileItem] = [] var body: some View { - List(files) {item in + List(files) { item in HStack { - AsyncImage(url: URL(string: item.thumbnail)) {image in + AsyncImage(url: URL(string: item.thumbnail)) { image in image.resizable() } placeholder: { ProgressView() } - .frame(width: 80, height: 40) + .frame(width: 80, height: 40) Text(item.name) NavigationLink(destination: PhotoSphereView(item)) {} } } .refreshable { Task { - await listPhotos {newFiles in + await listPhotos { newFiles in files = newFiles } } } - .onAppear() { + .onAppear { Task { - await listPhotos {newFiles in + await listPhotos { newFiles in files = newFiles } } @@ -49,17 +49,16 @@ struct ListPhotosView: View { .navigationBarBackButtonHidden(true) .navigationTitle(getTitle()) .navigationBarItems( - leading: + leading: HStack { Button(action: { self.presentation.wrappedValue.dismiss() }, label: { Image("chevron") - .resizable() - .frame(width: 24, height: 24) - } - ) + .resizable() + .frame(width: 24, height: 24) + }) } ) .listStyle(.plain) @@ -67,15 +66,15 @@ struct ListPhotosView: View { func listPhotos(_ done: @escaping (_ files: [FileItem]) -> Void) async { do { - try await theta.listPhotos {response in + try await theta.listPhotos { response in var newFiles: [FileItem] = [] response.forEach { newFiles.append( - FileItem( - name: $0.name, - url: $0.fileUrl, - thumbnail: $0.thumbnailUrl - )) + FileItem( + name: $0.name, + url: $0.fileUrl, + thumbnail: $0.thumbnailUrl + )) } done(newFiles) } diff --git a/demos/demo-ios/SdkSample/PhotoSphereView.swift b/demos/demo-ios/SdkSample/PhotoSphereView.swift index 79e216a470..1e80995255 100644 --- a/demos/demo-ios/SdkSample/PhotoSphereView.swift +++ b/demos/demo-ios/SdkSample/PhotoSphereView.swift @@ -12,6 +12,7 @@ struct PhotoSphereView: View { init(_ item: FileItem = FileItem()) { self.item = item } + var body: some View { VStack { if isClose { @@ -23,21 +24,20 @@ struct PhotoSphereView: View { .navigationBarBackButtonHidden(true) .navigationTitle(item.name) .navigationBarItems( - leading: + leading: HStack { Button(action: { - isClose = true - - DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { - self.presentation.wrappedValue.dismiss() - } + isClose = true + + DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { + self.presentation.wrappedValue.dismiss() + } }, label: { Image("chevron") - .resizable() - .frame(width: 24, height: 24) - } - ) + .resizable() + .frame(width: 24, height: 24) + }) } ) } diff --git a/demos/demo-ios/SdkSample/SphereViewer/SphereView.swift b/demos/demo-ios/SdkSample/SphereViewer/SphereView.swift index 270d534c6d..82b08017ff 100644 --- a/demos/demo-ios/SdkSample/SphereViewer/SphereView.swift +++ b/demos/demo-ios/SdkSample/SphereViewer/SphereView.swift @@ -9,11 +9,11 @@ import WebKit struct SphereView: UIViewRepresentable { var urlString: String - func makeUIView(context: Context) -> Viewer360 { + func makeUIView(context _: Context) -> Viewer360 { return Viewer360(frame: .zero) } - - func updateUIView(_ uiView: Viewer360, context: Context) { + + func updateUIView(_ uiView: Viewer360, context _: Context) { guard URL(string: urlString) != nil else { return } @@ -22,6 +22,6 @@ struct SphereView: UIViewRepresentable { static func jpegDataToDataUrl(data: Data) -> String { let DATA_URL_PREFIX = "data:image/jpeg;base64," - return DATA_URL_PREFIX + data.base64EncodedString(); + return DATA_URL_PREFIX + data.base64EncodedString() } } diff --git a/demos/demo-ios/SdkSample/SphereViewer/Viewer360.swift b/demos/demo-ios/SdkSample/SphereViewer/Viewer360.swift index 3b6250a12a..43e448322a 100644 --- a/demos/demo-ios/SdkSample/SphereViewer/Viewer360.swift +++ b/demos/demo-ios/SdkSample/SphereViewer/Viewer360.swift @@ -11,7 +11,7 @@ import WebKit class Viewer360: WKWebView, WKNavigationDelegate { var imageUrl: String? var isInitialized = false - + override init(frame: CGRect, configuration: WKWebViewConfiguration) { super.init(frame: frame, configuration: configuration) loadViewer() @@ -29,31 +29,30 @@ class Viewer360: WKWebView, WKNavigationDelegate { super.init(coder: coder) loadViewer() } - + func loadViewer() { navigationDelegate = self let path: String = Bundle.main.path(forResource: "index", ofType: "html")! - let localHtmlUrl: URL = URL(fileURLWithPath: path, isDirectory: false) + let localHtmlUrl = URL(fileURLWithPath: path, isDirectory: false) loadFileURL(localHtmlUrl, allowingReadAccessTo: localHtmlUrl) configuration.userContentController = WKUserContentController() } - + func updateImage(imageUrl: String) { self.imageUrl = imageUrl callUpdate() } - + func callUpdate() { if isInitialized && imageUrl != nil { evaluateJavaScript("update('\(imageUrl!)');") } } - + // MARK: - WKNavigationDelegate - - func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { + + func webView(_: WKWebView, didFinish _: WKNavigation!) { isInitialized = true - callUpdate(); + callUpdate() } - } diff --git a/demos/demo-ios/SdkSample/TakePhotoView.swift b/demos/demo-ios/SdkSample/TakePhotoView.swift index f11f34e288..e0761e3e79 100644 --- a/demos/demo-ios/SdkSample/TakePhotoView.swift +++ b/demos/demo-ios/SdkSample/TakePhotoView.swift @@ -14,71 +14,71 @@ struct TakePhotoView: View { var body: some View { ZStack { previewView - .frame(maxWidth: .infinity, maxHeight: .infinity) - .ignoresSafeArea() + .frame(maxWidth: .infinity, maxHeight: .infinity) + .ignoresSafeArea() VStack { Spacer() Button( - action: { - Task { - await takePhoto() - } - }, - label: { - Image("shutter") - } + action: { + Task { + await takePhoto() + } + }, + label: { + Image("shutter") + } ) Spacer().frame(height: 8) } hiddenLink.frame(width: 0, height: 0) } - .onAppear() { + .onAppear { self.previewing = true self.item = nil Task { do { try await theta.livePreview( - frameHandler: {frame in - preview = UIImage(data: frame) - return self.previewing - } + frameHandler: { frame in + preview = UIImage(data: frame) + return self.previewing + } ) } catch { self.previewing = false } } } - .onDisappear() { + .onDisappear { self.previewing = false } .navigationBarBackButtonHidden(true) .navigationTitle("Take Photo") .navigationBarItems( leading: - HStack { - Button(action: { - previewing = false - DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { - self.presentation.wrappedValue.dismiss() - } - }, - label: { - Image("chevron") - .resizable() - .frame(width: 24, height: 24) - } - ) - } + HStack { + Button(action: { + previewing = false + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + self.presentation.wrappedValue.dismiss() + } + }, + label: { + Image("chevron") + .resizable() + .frame(width: 24, height: 24) + }) + } ) } + var hiddenLink: some View { Group { if let fileItem = item { NavigationLink( - destination: PhotoSphereView(fileItem), - isActive: $isActive, - label: { - }) + destination: PhotoSphereView(fileItem), + isActive: $isActive, + label: {} + ) } else { EmptyView() } @@ -89,18 +89,18 @@ struct TakePhotoView: View { Group { if let image = preview { Image(uiImage: image) - .resizable() - .scaledToFit() + .resizable() + .scaledToFit() } else { ProgressView() - .scaleEffect(x: 2.0, y: 2.0) - .progressViewStyle(CircularProgressViewStyle(tint: Color(purple_700))) + .scaleEffect(x: 2.0, y: 2.0) + .progressViewStyle(CircularProgressViewStyle(tint: Color(purple_700))) } } } func takePhoto() async { - if (!previewing) { + if !previewing { return } previewing = false diff --git a/demos/demo-ios/SdkSample/ThetaSdk.swift b/demos/demo-ios/SdkSample/ThetaSdk.swift index a33df3b6d4..cf0c171e40 100644 --- a/demos/demo-ios/SdkSample/ThetaSdk.swift +++ b/demos/demo-ios/SdkSample/ThetaSdk.swift @@ -2,8 +2,8 @@ // ThetaSdk.swift // SdkSample // -import UIKit import THETAClient +import UIKit typealias ThetaHandlerWithError = (_ response: T?, _ error: Error?) -> Void typealias ThetaHandler = (_ response: T) -> Void @@ -19,16 +19,16 @@ let theta = Theta() class Theta { static let endPoint: String = "http://192.168.1.1" - var thetaRepository: ThetaRepository? = nil - var lastInfo: ThetaInfo? = nil + var thetaRepository: ThetaRepository? + var lastInfo: ThetaInfo? func reset() { thetaRepository = nil } func initialize() async throws { - if (thetaRepository != nil) { - return; + if thetaRepository != nil { + return } var config: ThetaRepository.Config? @@ -36,12 +36,12 @@ class Theta { // config = ThetaRepository.Config() // config.clientMode = DigestAuth(username: "THETAXX12345678", password: "12345678") - thetaRepository = try await withCheckedThrowingContinuation {continuation in + thetaRepository = try await withCheckedThrowingContinuation { continuation in ThetaRepository.Companion.shared.doNewInstance( - endpoint:Self.endPoint, - config:config, - timeout:nil - ) {resp, error in + endpoint: Self.endPoint, + config: config, + timeout: nil + ) { resp, error in if let response = resp { continuation.resume(returning: response) } @@ -54,8 +54,8 @@ class Theta { func info(_ completionHandler: @escaping ThetaHandler) async throws { try await initialize() - let response: ThetaInfo = try await withCheckedThrowingContinuation {continuation in - thetaRepository!.getThetaInfo {resp, error in + let response: ThetaInfo = try await withCheckedThrowingContinuation { continuation in + thetaRepository!.getThetaInfo { resp, error in if let response = resp { continuation.resume(returning: response) } @@ -67,19 +67,20 @@ class Theta { lastInfo = response completionHandler(response) } - + func livePreview(frameHandler: @escaping ThetaFrameHandler) async throws { try await initialize() class FrameHandler: KotlinSuspendFunction1 { - static let FrameInterval = CFTimeInterval(1.0/10.0) + static let FrameInterval = CFTimeInterval(1.0 / 10.0) let handler: ThetaFrameHandler var last: CFTimeInterval = 0 init(_ handler: @escaping ThetaFrameHandler) { self.handler = handler } + func invoke(p1: Any?) async throws -> Any? { let now = CACurrentMediaTime() - if (now - last > Self.FrameInterval) { + if now - last > Self.FrameInterval { var result = false autoreleasepool { if let frameData = p1 as? KotlinPair { @@ -96,10 +97,10 @@ class Theta { } } } - let _:Bool = try await withCheckedThrowingContinuation {continuation in + let _: Bool = try await withCheckedThrowingContinuation { continuation in thetaRepository!.getLivePreview( - frameHandler: FrameHandler(frameHandler) - ) {error in + frameHandler: FrameHandler(frameHandler) + ) { error in if let thetaError = error { continuation.resume(throwing: thetaError) } else { @@ -112,59 +113,61 @@ class Theta { func listPhotos(_ completionHandler: @escaping ThetaHandler<[ThetaFileInfo]>) async throws { try await initialize() let response: [ThetaFileInfo] - = try await withCheckedThrowingContinuation {continuation in - thetaRepository!.listFiles(fileType: ThetaFileType.image, startPosition: 0, - entryCount: 1000) {resp, error in - if let response = resp { - continuation.resume(returning: response.fileList) - } - if let thetaError = error { - continuation.resume(throwing: thetaError) - } - } - } + = try await withCheckedThrowingContinuation { continuation in + thetaRepository!.listFiles(fileType: ThetaFileType.image, startPosition: 0, + entryCount: 1000) + { resp, error in + if let response = resp { + continuation.resume(returning: response.fileList) + } + if let thetaError = error { + continuation.resume(throwing: thetaError) + } + } + } completionHandler(response) } func takePicture(_ callback: @escaping (_ url: String?) -> Void) async throws { try await initialize() - let photoCapture: PhotoCapture = try await withCheckedThrowingContinuation {continuation in + let photoCapture: PhotoCapture = try await withCheckedThrowingContinuation { continuation in thetaRepository!.getPhotoCaptureBuilder() - .build {capture, error in - if let photoCapture = capture { - continuation.resume(returning: photoCapture) - } - if let thetaError = error { - continuation.resume(throwing: thetaError) - } - } + .build { capture, error in + if let photoCapture = capture { + continuation.resume(returning: photoCapture) + } + if let thetaError = error { + continuation.resume(throwing: thetaError) + } + } } class Callback: PhotoCaptureTakePictureCallback { let callback: (_ url: String?, _ error: Error?) -> Void init(_ callback: @escaping (_ url: String?, _ error: Error?) -> Void) { self.callback = callback } + func onSuccess(fileUrl: String?) { callback(fileUrl, nil) } - func onProgress(completion: Float) { - } + + func onProgress(completion _: Float) {} + func onError(exception: ThetaException) { callback(nil, exception.asError()) } } - let photoUrl: String? = try await withCheckedThrowingContinuation {continuation in + let photoUrl: String? = try await withCheckedThrowingContinuation { continuation in photoCapture.takePicture( - callback: Callback {fileUrl, error in - if let thetaError = error { - continuation.resume(throwing: thetaError) - } else { - continuation.resume(returning: fileUrl) - } - } + callback: Callback { fileUrl, error in + if let thetaError = error { + continuation.resume(throwing: thetaError) + } else { + continuation.resume(returning: fileUrl) + } + } ) } callback(photoUrl) } } - diff --git a/demos/demo-ios/SdkSample/UIColorHex.swift b/demos/demo-ios/SdkSample/UIColorHex.swift index 1df15c5324..aa84d3c73c 100644 --- a/demos/demo-ios/SdkSample/UIColorHex.swift +++ b/demos/demo-ios/SdkSample/UIColorHex.swift @@ -6,19 +6,19 @@ import UIKit extension UIColor { convenience init(hex: String) { - var colors:[CGFloat] = Array(repeating: CGFloat(1.0), count: 4) + var colors: [CGFloat] = Array(repeating: CGFloat(1.0), count: 4) var color = UInt32(hex, radix: 16)! - if (hex.count == 3) { + if hex.count == 3 { for i in 0 ..< 3 { colors[2 - i] = CGFloat(color % 16) / CGFloat(16) color /= 16 } - } else if (hex.count == 6) { + } else if hex.count == 6 { for i in 0 ..< 3 { colors[2 - i] = CGFloat(color % 256) / CGFloat(256) color /= 256 } - } else if (hex.count == 8) { + } else if hex.count == 8 { for i in 0 ..< 4 { colors[3 - i] = CGFloat(color % 256) / CGFloat(256) color /= 256 diff --git a/demos/demo-react-native/package.json b/demos/demo-react-native/package.json index 84486f0039..0626d8ab05 100644 --- a/demos/demo-react-native/package.json +++ b/demos/demo-react-native/package.json @@ -13,7 +13,7 @@ "dependencies": { "@react-navigation/native": "^6.1.0", "@react-navigation/native-stack": "^6.9.5", - "theta-client-react-native": "1.5.0", + "theta-client-react-native": "1.6.0", "react": "18.2.0", "react-native": "0.71.14", "react-native-safe-area-context": "^4.4.1", diff --git a/flutter/android/build.gradle b/flutter/android/build.gradle index 0a4273cf66..90762cbded 100644 --- a/flutter/android/build.gradle +++ b/flutter/android/build.gradle @@ -53,5 +53,5 @@ dependencies { implementation("io.ktor:ktor-serialization-kotlinx-json:2.1.2") implementation("com.soywiz.korlibs.krypto:krypto:3.4.0") - implementation("com.ricoh360.thetaclient:theta-client:1.5.0") + implementation("com.ricoh360.thetaclient:theta-client:1.6.0") } diff --git a/flutter/ios/Classes/ConvertUtil.swift b/flutter/ios/Classes/ConvertUtil.swift index 09e6724fbf..82c4552970 100644 --- a/flutter/ios/Classes/ConvertUtil.swift +++ b/flutter/ios/Classes/ConvertUtil.swift @@ -266,7 +266,7 @@ func setShotCountSpecifiedIntervalCaptureBuilderParams(params: [String: Any], bu func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingList { let autoBracket = ThetaRepository.BracketSettingList(list: NSMutableArray()) - + params.forEach { map in let aperture = { if let name = map["aperture"] as? String { @@ -275,7 +275,7 @@ func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingLis return nil } }() - + let colorTemperature = { if let value = map["colorTemperature"] as? Int { return toKotlinInt(value: value) @@ -283,7 +283,7 @@ func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingLis return nil } }() - + let exposureCompensation = { if let name = map["exposureCompensation"] as? String { return getEnumValue(values: ThetaRepository.ExposureCompensationEnum.values(), name: name) @@ -291,7 +291,7 @@ func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingLis return nil } }() - + let exposureProgram = { if let name = map["exposureProgram"] as? String { return getEnumValue(values: ThetaRepository.ExposureProgramEnum.values(), name: name) @@ -299,7 +299,7 @@ func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingLis return nil } }() - + let iso = { if let name = map["iso"] as? String { return getEnumValue(values: ThetaRepository.IsoEnum.values(), name: name) @@ -307,7 +307,7 @@ func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingLis return nil } }() - + let shutterSpeed = { if let name = map["shutterSpeed"] as? String { return getEnumValue(values: ThetaRepository.ShutterSpeedEnum.values(), name: name) @@ -315,7 +315,7 @@ func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingLis return nil } }() - + let whiteBalance = { if let name = map["whiteBalance"] as? String { return getEnumValue(values: ThetaRepository.WhiteBalanceEnum.values(), name: name) @@ -323,7 +323,7 @@ func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingLis return nil } }() - + autoBracket.add(setting: ThetaRepository.BracketSetting( aperture: aperture, colorTemperature: colorTemperature, @@ -334,13 +334,13 @@ func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingLis whiteBalance: whiteBalance )) } - + return autoBracket } func convertResult(autoBracket: ThetaRepository.BracketSettingList) -> [[String: Any]] { var resultList = [[String: Any]]() - + autoBracket.list.forEach { bracketSetting in if let setting = bracketSetting as? ThetaRepository.BracketSetting { resultList.append([ @@ -354,7 +354,7 @@ func convertResult(autoBracket: ThetaRepository.BracketSettingList) -> [[String: ]) } } - + return resultList } @@ -592,7 +592,7 @@ func setOptionsValue(options: ThetaRepository.Options, name: String, value: Any) case ThetaRepository.OptionNameEnum.aperture.name: options.aperture = getEnumValue(values: ThetaRepository.ApertureEnum.values(), name: value as! String)! case ThetaRepository.OptionNameEnum.autobracket.name: - if let params = value as? [[String:Any]] { + if let params = value as? [[String: Any]] { options.autoBracket = toAutoBracket(params: params) } case ThetaRepository.OptionNameEnum.bitrate.name: diff --git a/flutter/ios/Classes/SwiftThetaClientFlutterPlugin.swift b/flutter/ios/Classes/SwiftThetaClientFlutterPlugin.swift index 174dd4ab90..df1bcd9ba4 100644 --- a/flutter/ios/Classes/SwiftThetaClientFlutterPlugin.swift +++ b/flutter/ios/Classes/SwiftThetaClientFlutterPlugin.swift @@ -50,7 +50,7 @@ public class SwiftThetaClientFlutterPlugin: NSObject, FlutterPlugin, FlutterStre var compositeIntervalCaptureBuilder: CompositeIntervalCapture.Builder? = nil var compositeIntervalCapture: CompositeIntervalCapture? = nil var compositeIntervalCapturing: CompositeIntervalCapturing? = nil - + public static func register(with registrar: FlutterPluginRegistrar) { let channel = FlutterMethodChannel(name: "theta_client_flutter", binaryMessenger: registrar.messenger()) let instance = SwiftThetaClientFlutterPlugin() @@ -558,20 +558,20 @@ public class SwiftThetaClientFlutterPlugin: NSObject, FlutterPlugin, FlutterStre self.callback = callback self.plugin = plugin } - + func onCaptureFailed(exception: ThetaRepository.ThetaRepositoryException) { callback(nil, exception.asError()) } - + func onStopFailed(exception: ThetaRepository.ThetaRepositoryException) { let error = exception.asError() plugin?.sendNotifyEvent(id: NOTIFY_TIME_SHIFT_STOP_ERROR, params: toMessageNotifyParam(message: error.localizedDescription)) } - + func onProgress(completion: Float) { plugin?.sendNotifyEvent(id: NOTIFY_TIME_SHIFT_PROGRESS, params: toCaptureProgressNotifyParam(value: completion)) } - + func onCaptureCompleted(fileUrl: String?) { callback(fileUrl, nil) } @@ -850,7 +850,7 @@ public class SwiftThetaClientFlutterPlugin: NSObject, FlutterPlugin, FlutterStre capturing.stopCapture() result(nil) } - + func getCompositeIntervalCaptureBuilder(call: FlutterMethodCall, result: @escaping FlutterResult) { guard let thetaRepository else { let flutterError = FlutterError(code: SwiftThetaClientFlutterPlugin.errorCode, message: SwiftThetaClientFlutterPlugin.messageNotInit, details: nil) @@ -862,7 +862,7 @@ public class SwiftThetaClientFlutterPlugin: NSObject, FlutterPlugin, FlutterStre } result(nil) } - + func buildCompositeIntervalCapture(call: FlutterMethodCall, result: @escaping FlutterResult) { guard let _ = thetaRepository, let builder = compositeIntervalCaptureBuilder else { let flutterError = FlutterError(code: SwiftThetaClientFlutterPlugin.errorCode, message: SwiftThetaClientFlutterPlugin.messageNotInit, details: nil) @@ -883,7 +883,7 @@ public class SwiftThetaClientFlutterPlugin: NSObject, FlutterPlugin, FlutterStre } }) } - + func startCompositeIntervalCapture(result: @escaping FlutterResult) { guard let _ = thetaRepository, let capture = compositeIntervalCapture else { let flutterError = FlutterError(code: SwiftThetaClientFlutterPlugin.errorCode, message: SwiftThetaClientFlutterPlugin.messageNotInit, details: nil) @@ -897,38 +897,38 @@ public class SwiftThetaClientFlutterPlugin: NSObject, FlutterPlugin, FlutterStre self.callback = callback self.plugin = plugin } - + func onCaptureFailed(exception: ThetaRepository.ThetaRepositoryException) { callback(nil, exception.asError()) } - + func onStopFailed(exception: ThetaRepository.ThetaRepositoryException) { let error = exception.asError() plugin?.sendNotifyEvent(id: NOTIFY_COMPOSITE_INTERVAL_STOP_ERROR, params: toMessageNotifyParam(message: error.localizedDescription)) } - + func onProgress(completion: Float) { plugin?.sendNotifyEvent(id: NOTIFY_COMPOSITE_INTERVAL_PROGRESS, params: toCaptureProgressNotifyParam(value: completion)) } - + func onCaptureCompleted(fileUrls: [String]?) { callback(fileUrls, nil) } } - + compositeIntervalCapturing = capture.startCapture( callback: Callback({ fileUrl, error in - if let thetaError = error { - let flutterError = FlutterError(code: SwiftThetaClientFlutterPlugin.errorCode, message: thetaError.localizedDescription, details: nil) - result(flutterError) - } else { - result(fileUrl) - } - }, + if let thetaError = error { + let flutterError = FlutterError(code: SwiftThetaClientFlutterPlugin.errorCode, message: thetaError.localizedDescription, details: nil) + result(flutterError) + } else { + result(fileUrl) + } + }, plugin: self) ) } - + func stopCompositeIntervalCapture(result: @escaping FlutterResult) { guard let _ = thetaRepository, let capturing = compositeIntervalCapturing else { let flutterError = FlutterError(code: SwiftThetaClientFlutterPlugin.errorCode, message: SwiftThetaClientFlutterPlugin.messageNotInit, details: nil) diff --git a/flutter/ios/theta_client_flutter.podspec b/flutter/ios/theta_client_flutter.podspec index 66c3973220..433fa945aa 100644 --- a/flutter/ios/theta_client_flutter.podspec +++ b/flutter/ios/theta_client_flutter.podspec @@ -4,7 +4,7 @@ # Pod::Spec.new do |s| s.name = 'theta_client_flutter' - s.version = '1.5.0' + s.version = '1.6.0' s.summary = 'theta-client plugin project.' s.description = <<-DESC theta-client Flutter plugin project. @@ -17,7 +17,7 @@ Pod::Spec.new do |s| s.dependency 'Flutter' s.platform = :ios, '15.0' - s.dependency 'THETAClient', '1.5.0' + s.dependency 'THETAClient', '1.6.0' # Flutter.framework does not contain a i386 slice. s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } diff --git a/flutter/lib/theta_client_flutter.dart b/flutter/lib/theta_client_flutter.dart index ed48d9fa90..c5634da535 100644 --- a/flutter/lib/theta_client_flutter.dart +++ b/flutter/lib/theta_client_flutter.dart @@ -155,8 +155,8 @@ class ThetaClientFlutter { } /// Get getCompositeIntervalCapture.Builder for capture interval composite shooting. - CompositeIntervalCaptureBuilder - getCompositeIntervalCaptureBuilder(int shootingTimeSec) { + CompositeIntervalCaptureBuilder getCompositeIntervalCaptureBuilder( + int shootingTimeSec) { ThetaClientFlutterPlatform.instance .getCompositeIntervalCaptureBuilder(shootingTimeSec); return CompositeIntervalCaptureBuilder(); diff --git a/flutter/lib/theta_client_flutter_method_channel.dart b/flutter/lib/theta_client_flutter_method_channel.dart index d664033618..637f3ef935 100644 --- a/flutter/lib/theta_client_flutter_method_channel.dart +++ b/flutter/lib/theta_client_flutter_method_channel.dart @@ -431,8 +431,7 @@ class MethodChannelThetaClientFlutter extends ThetaClientFlutterPlatform { } @override - Future getCompositeIntervalCaptureBuilder( - int shootingTimeSec) async { + Future getCompositeIntervalCaptureBuilder(int shootingTimeSec) async { return methodChannel.invokeMethod( 'getCompositeIntervalCaptureBuilder', shootingTimeSec); } @@ -469,7 +468,8 @@ class MethodChannelThetaClientFlutter extends ThetaClientFlutterPlatform { } }); } - final fileUrls = await methodChannel.invokeMethod?>('startCompositeIntervalCapture'); + final fileUrls = await methodChannel + .invokeMethod?>('startCompositeIntervalCapture'); removeNotify(notifyIdCompositeIntervalCaptureProgress); removeNotify(notifyIdCompositeIntervalCaptureStopError); if (fileUrls == null) { @@ -487,8 +487,7 @@ class MethodChannelThetaClientFlutter extends ThetaClientFlutterPlatform { @override Future stopCompositeIntervalCapture() async { - return methodChannel - .invokeMethod('stopCompositeIntervalCapture'); + return methodChannel.invokeMethod('stopCompositeIntervalCapture'); } @override diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index cb1a232770..72b9e06c67 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,6 +1,6 @@ name: theta_client_flutter description: THETA Client Flutter plugin project. -version: 1.5.0 +version: 1.6.0 homepage: environment: diff --git a/flutter/test/capture/photo_capture_test.dart b/flutter/test/capture/photo_capture_test.dart index 703ea98b12..86d811a115 100644 --- a/flutter/test/capture/photo_capture_test.dart +++ b/flutter/test/capture/photo_capture_test.dart @@ -12,7 +12,7 @@ void main() { test('getPhotoCaptureBuilder', () async { ThetaClientFlutter thetaClientPlugin = ThetaClientFlutter(); MockThetaClientFlutterPlatform fakePlatform = - MockThetaClientFlutterPlatform(); + MockThetaClientFlutterPlatform(); ThetaClientFlutterPlatform.instance = fakePlatform; onCallGetPhotoCaptureBuilder = Future.value; @@ -24,7 +24,7 @@ void main() { test('buildPhotoCapture', () async { ThetaClientFlutter thetaClientPlugin = ThetaClientFlutter(); MockThetaClientFlutterPlatform fakePlatform = - MockThetaClientFlutterPlatform(); + MockThetaClientFlutterPlatform(); ThetaClientFlutterPlatform.instance = fakePlatform; onCallGetPhotoCaptureBuilder = Future.value; @@ -105,7 +105,7 @@ void main() { test('takePicture', () async { ThetaClientFlutter thetaClientPlugin = ThetaClientFlutter(); MockThetaClientFlutterPlatform fakePlatform = - MockThetaClientFlutterPlatform(); + MockThetaClientFlutterPlatform(); ThetaClientFlutterPlatform.instance = fakePlatform; const imageUrl = 'http://test.jpg'; @@ -133,7 +133,7 @@ void main() { test('takePicture Exception', () async { ThetaClientFlutter thetaClientPlugin = ThetaClientFlutter(); MockThetaClientFlutterPlatform fakePlatform = - MockThetaClientFlutterPlatform(); + MockThetaClientFlutterPlatform(); ThetaClientFlutterPlatform.instance = fakePlatform; onCallGetPhotoCaptureBuilder = Future.value; diff --git a/flutter/test/capture/time_shift_capture_test.dart b/flutter/test/capture/time_shift_capture_test.dart index c3e7cca423..b2a812394a 100644 --- a/flutter/test/capture/time_shift_capture_test.dart +++ b/flutter/test/capture/time_shift_capture_test.dart @@ -172,8 +172,7 @@ void main() { return Future.value(); }; - var builder = thetaClientPlugin - .getTimeShiftCaptureBuilder(); + var builder = thetaClientPlugin.getTimeShiftCaptureBuilder(); var capture = await builder.build(); var isOnStopFailed = false; var capturing = capture.startCapture( diff --git a/flutter/test/theta_client_flutter_test.dart b/flutter/test/theta_client_flutter_test.dart index 9476009f80..5166dfabe1 100644 --- a/flutter/test/theta_client_flutter_test.dart +++ b/flutter/test/theta_client_flutter_test.dart @@ -351,7 +351,8 @@ Future Function() onCallTakePicture = Future.value; Future Function() onCallGetTimeShiftCaptureBuilder = Future.value; Future Function(Map options, int interval) onCallBuildTimeShiftCapture = (options, interval) => Future.value(); -Future Function(void Function(double)? onProgress, void Function(Exception exception)? onStopFailed) +Future Function(void Function(double)? onProgress, + void Function(Exception exception)? onStopFailed) onCallStartTimeShiftCapture = (onProgress, onStopFailed) => Future.value(); Future Function() onCallStopTimeShiftCapture = Future.value; Future Function() onCallGetVideoCaptureBuilder = Future.value; diff --git a/kotlin-multiplatform/build.gradle.kts b/kotlin-multiplatform/build.gradle.kts index 200364d805..ff4e02977a 100644 --- a/kotlin-multiplatform/build.gradle.kts +++ b/kotlin-multiplatform/build.gradle.kts @@ -17,7 +17,7 @@ dependencies { dokkaPlugin("org.jetbrains.dokka:versioning-plugin:1.9.10") } -val thetaClientVersion = "1.5.0" +val thetaClientVersion = "1.6.0" group = "com.ricoh360.thetaclient" version = thetaClientVersion diff --git a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaRepository.kt b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaRepository.kt index 5f7471b0e7..3d813e8201 100644 --- a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaRepository.kt +++ b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaRepository.kt @@ -1891,7 +1891,7 @@ class ThetaRepository internal constructor(val endpoint: String, config: Config? /** * Parameters for multi bracket shooting. */ - data class BracketSetting ( + data class BracketSetting( /** * Aperture value. * Theta X and SC2 do not support. diff --git a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/transferred/setOptionsCommand.kt b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/transferred/setOptionsCommand.kt index df7f4fd2e7..ab65e56eb6 100644 --- a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/transferred/setOptionsCommand.kt +++ b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/transferred/setOptionsCommand.kt @@ -799,7 +799,7 @@ internal data class Options( * For [_bracketParameters], all parameters must be specified. */ @Serializable -internal data class AutoBracket ( +internal data class AutoBracket( /** * Number of shots in multi bracket shooting. * 2 to 13 (THETA X and SC2); @@ -817,7 +817,7 @@ internal data class AutoBracket ( * Parameter array specified for multi bracket shooting */ @Serializable -internal data class BracketParameter ( +internal data class BracketParameter( /** * Aperture value. * Theta X and SC2 do not support. diff --git a/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/capture/TimeShiftCaptureTest.kt b/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/capture/TimeShiftCaptureTest.kt index 498fb2dad7..ebb4bb74d6 100644 --- a/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/capture/TimeShiftCaptureTest.kt +++ b/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/capture/TimeShiftCaptureTest.kt @@ -92,6 +92,7 @@ class TimeShiftCaptureTest { assertTrue(false, "error start time-shift") deferred.complete(Unit) } + override fun onStopFailed(exception: ThetaRepository.ThetaRepositoryException) { assertTrue(false, "error start time-shift") deferred.complete(Unit) @@ -170,6 +171,7 @@ class TimeShiftCaptureTest { assertTrue(false, "error start time-shift") deferred.complete(Unit) } + override fun onStopFailed(exception: ThetaRepository.ThetaRepositoryException) { assertTrue(false, "error start time-shift") deferred.complete(Unit) diff --git a/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/repository/options/OptionsTest.kt b/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/repository/options/OptionsTest.kt index b990e4feca..6d7404d2a9 100644 --- a/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/repository/options/OptionsTest.kt +++ b/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/repository/options/OptionsTest.kt @@ -275,7 +275,8 @@ class OptionsTest { val values = listOf( Pair(ThetaRepository.OptionNameEnum.AiAutoThumbnail, ThetaRepository.AiAutoThumbnailEnum.OFF), Pair(ThetaRepository.OptionNameEnum.Aperture, ThetaRepository.ApertureEnum.APERTURE_2_1), - Pair(ThetaRepository.OptionNameEnum.AutoBracket, + Pair( + ThetaRepository.OptionNameEnum.AutoBracket, ThetaRepository.BracketSettingList().add( ThetaRepository.BracketSetting( exposureProgram = ThetaRepository.ExposureProgramEnum.NORMAL_PROGRAM, diff --git a/react-native/android/build.gradle b/react-native/android/build.gradle index 4b5458715e..54fff8ed40 100644 --- a/react-native/android/build.gradle +++ b/react-native/android/build.gradle @@ -135,7 +135,7 @@ dependencies { implementation "com.facebook.react:react-native:+" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4" - implementation "com.ricoh360.thetaclient:theta-client:1.5.0" + implementation "com.ricoh360.thetaclient:theta-client:1.6.0" // From node_modules } diff --git a/react-native/android/src/main/java/com/ricoh360/thetaclientreactnative/Converter.kt b/react-native/android/src/main/java/com/ricoh360/thetaclientreactnative/Converter.kt index 5dd7f2a6c7..56a8f03a3a 100644 --- a/react-native/android/src/main/java/com/ricoh360/thetaclientreactnative/Converter.kt +++ b/react-native/android/src/main/java/com/ricoh360/thetaclientreactnative/Converter.kt @@ -612,7 +612,7 @@ fun toListAccessPointsResult(accessPointList: List): WritableArray fun toAutoBracket(list: ReadableArray): BracketSettingList { val autoBracket = BracketSettingList() - for(i in 0 until list.size()) { + for (i in 0 until list.size()) { list.getMap(i)?.let { setting -> autoBracket.add( BracketSetting( diff --git a/react-native/ios/ConvertUtil.swift b/react-native/ios/ConvertUtil.swift index 5c757b8603..0a22b5eb5c 100644 --- a/react-native/ios/ConvertUtil.swift +++ b/react-native/ios/ConvertUtil.swift @@ -765,7 +765,7 @@ func convertResult(burstOption: ThetaRepository.BurstOption) -> [String: Any] { func convertResult(autoBracket: ThetaRepository.BracketSettingList) -> [[String: Any]] { var resultList = [[String: Any]]() - + autoBracket.list.forEach { bracketSetting in var result: [String: Any] = [:] if let setting = bracketSetting as? ThetaRepository.BracketSetting { @@ -793,7 +793,7 @@ func convertResult(autoBracket: ThetaRepository.BracketSettingList) -> [[String: resultList.append(result) } } - + return resultList } @@ -998,7 +998,7 @@ func toBurstOption(params: [String: Any]) -> ThetaRepository.BurstOption { func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingList { let autoBracket = ThetaRepository.BracketSettingList(list: NSMutableArray()) - + params.forEach { map in let aperture = { if let name = map["aperture"] as? String { @@ -1007,7 +1007,7 @@ func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingLis return nil } }() - + let colorTemperature = { if let value = map["colorTemperature"] as? Int { return toKotlinInt(value: value) @@ -1015,7 +1015,7 @@ func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingLis return nil } }() - + let exposureCompensation = { if let name = map["exposureCompensation"] as? String { return getEnumValue(values: ThetaRepository.ExposureCompensationEnum.values(), name: name) @@ -1023,7 +1023,7 @@ func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingLis return nil } }() - + let exposureProgram = { if let name = map["exposureProgram"] as? String { return getEnumValue(values: ThetaRepository.ExposureProgramEnum.values(), name: name) @@ -1031,7 +1031,7 @@ func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingLis return nil } }() - + let iso = { if let name = map["iso"] as? String { return getEnumValue(values: ThetaRepository.IsoEnum.values(), name: name) @@ -1039,7 +1039,7 @@ func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingLis return nil } }() - + let shutterSpeed = { if let name = map["shutterSpeed"] as? String { return getEnumValue(values: ThetaRepository.ShutterSpeedEnum.values(), name: name) @@ -1047,7 +1047,7 @@ func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingLis return nil } }() - + let whiteBalance = { if let name = map["whiteBalance"] as? String { return getEnumValue(values: ThetaRepository.WhiteBalanceEnum.values(), name: name) @@ -1055,7 +1055,7 @@ func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingLis return nil } }() - + autoBracket.add(setting: ThetaRepository.BracketSetting( aperture: aperture, colorTemperature: colorTemperature, @@ -1066,7 +1066,7 @@ func toAutoBracket(params: [[String: Any]]) -> ThetaRepository.BracketSettingLis whiteBalance: whiteBalance )) } - + return autoBracket } diff --git a/react-native/ios/ThetaClientReactNative.swift b/react-native/ios/ThetaClientReactNative.swift index 372ce707dd..070e4d635c 100644 --- a/react-native/ios/ThetaClientReactNative.swift +++ b/react-native/ios/ThetaClientReactNative.swift @@ -55,7 +55,7 @@ class ThetaClientReactNative: RCTEventEmitter { static let NOTIFY_LIMITLESS_INTERVAL_CAPTURE_STOP_ERROR = "LIMITLESS-INTERVAL-CAPTURE-STOP-ERROR" static let NOTIFY_COMPOSITE_INTERVAL_PROGRESS = "COMPOSITE-INTERVAL-PROGRESS" static let NOTIFY_COMPOSITE_INTERVAL_STOP_ERROR = "COMPOSITE-INTERVAL-STOP-ERROR" - + @objc override func supportedEvents() -> [String]! { return [ThetaClientReactNative.EVENT_FRAME, ThetaClientReactNative.EVENT_NOTIFY] @@ -1023,7 +1023,7 @@ class ThetaClientReactNative: RCTEventEmitter { shotCountSpecifiedIntervalCapturing.cancelCapture() resolve(nil) } - + @objc(getCompositeIntervalCaptureBuilder:withResolver:withRejecter:) func getCompositeIntervalCaptureBuilder( shootingTimeSec: Int, diff --git a/react-native/package.json b/react-native/package.json index 299625f850..cb0266fc3c 100644 --- a/react-native/package.json +++ b/react-native/package.json @@ -1,6 +1,6 @@ { "name": "theta-client-react-native", - "version": "1.5.0", + "version": "1.6.0", "description": "This library provides a way to control RICOH THETA using.", "main": "lib/commonjs/index", "module": "lib/module/index", diff --git a/react-native/theta-client-react-native.podspec b/react-native/theta-client-react-native.podspec index e3e956a305..3f41a3e2bf 100644 --- a/react-native/theta-client-react-native.podspec +++ b/react-native/theta-client-react-native.podspec @@ -17,7 +17,7 @@ Pod::Spec.new do |s| s.source_files = "ios/**/*.{h,m,mm,swift}" s.dependency "React-Core" - s.dependency "THETAClient", "1.5.0" + s.dependency "THETAClient", "1.6.0" # Don't install the dependencies when we run `pod install` in the old architecture. if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then