How to use Web Speech API in Kotlin Multiplatform for web application - kotlin

Do you know how to use Web Speech API in KMM project for Web application: https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API/Using_the_Web_Speech_API
I'm using Kotlin to build the web app, and the web app require speech to text feature.

I'm not familiar with this particular WEB API, but here's the general process of wrapping global JS APIs in Kotlin so hopefully you'll be able to correct the odd inconsistencies yourself via trial and error.
Firstly, since the target API is global, there's no need for any meta-information for the compiler about where to source JS code from - it's present in the global context. Therefore, we only need to declare the shape of that global context. Normally that would be a straightforward task as outlined in this article, however there's a caveat here which requires some trickery to make it work on all the browsers:
As mentioned earlier, Chrome currently supports speech recognition with prefixed properties, therefore at the start of our code we include these lines to feed the right objects to Chrome, and any future implementations that might support the features without a prefix:
var SpeechRecognition = window.SpeechRecognition || webkitSpeechRecognition;
var SpeechGrammarList = window.SpeechGrammarList || webkitSpeechGrammarList;
var SpeechRecognitionEvent = window.SpeechRecognitionEvent || >webkitSpeechRecognitionEvent;
But let's ignore that for now since the API shape is consistent across the implementation, and name is the only difference that we'll address later. Two main API entities we need to wrap here are SpeechRecognition and SpeechGrammarList, both being classes. However, to make it easier to bridge the inconsistent names for them later on, in Kotlin it's best to describe their shapes as external interfaces. The process for both is the same, so I'll just outline it for SpeechRecognition.
First, the interface declaration. Here we can already make use from EventTarget declaration in Kotlin/JS stdlib. Note that the name of it does not matter here and will not clash with webkitSpeechRecognition when present since we declare it as an interface and as such we only care about the API shape.
external interface SpeechRecognition: EventTarget {
val grammars: SpeechGrammarList // or dynamic if you don't want to declare nested types
var lang: String
// etc...
}
Once we have the API shape declared, we need to bridge naming inconsistencies and provide a unified way to construct its instances from Kotlin. For that, we'll inject some hacky Kotlin code to act as our constructors.
// We match the function name to the type name here so that from Kotlin consumer's perspective it's indistinguishable from an actual constructor.
fun SpeechRecognition(): SpeechRecognition {
// Using some direct JS code to get an appropriate class reference
val cls = js("window.SpeechRecognition || webkitSpeechRecognition")
// Using the class reference to construct an instance of it and then tell the kotlin compiler to assume it's type
return js("new cls()").unsafeCast<SpeechRecognition>()
}
Hopefully this gives you the general idea of how things tie together. Let me know if something's still not quite clear.

Related

Why does the author need to set dependency injection in Domain Layer with Clean Architecture?

I'm learning Clean Architecture with the artical .
I know Domain Layer is the most INNER part of the onion (no dependencies with other layers) and it contains Entities, Use cases & Repository Interfaces.
The following code is from the project https://github.com/lopspower/CleanRxArchitecture
GetListRepo.kt and RepoRepository.kt are located in Domain Layer, you can see Image 1
1: I think the GetListRepo class should be abstract or interface, right?
2: There are three parameters for constructor of the class GetListRepo. I don't understand why the author add dependency injection #Inject for the class's constructor.
I think I can instance GetListRepo with any way in Data Layout, why does the author need to set dependency injection in Domain Layer with Clean Architecture ?
GetListRepo.kt
class GetListRepo
#Inject internal constructor(
private val repoRepository: RepoRepository,
useCaseScheduler: UseCaseScheduler? = null,
logger: Logger? = null
) : SingleUseCase<List<Repo>, String>(useCaseScheduler, logger) {
...
}
RepoRepository.kt
interface RepoRepository {
val isConnected: Boolean
...
}
Image 1
This is similar to your another question about interfaces/abstract classes. I will quote myself:
With such architecture you could create alternative implementations of GetAlbumListUseCase in the future and switch them smoothly. You could even use multiple implementations at the same time, for example different objects use different implementations GetAlbumListUseCase. Note that in your current architecture all objects directly depend on a specific implementation, so switching to another one requires to modify half of your code.
Imagine you did as you suggested, you didn't use dependency injection, but you created GetListRepo object everywhere in your code. Then in the future you need to have two alternative ways of providing the data, e.g. with local files and with remote server. Imagine you need to make it configurable in the application settings. Or imagine that you need to create unit tests and it would be good to provide a fake, testing variant of the GetListRepo.
How would you do this if your code everywhere would just instantiate GetListRepo directly? You would need to modify many different places in the code and put some logic related to loading of application settings, etc. everywhere. By using dependency injection all components receive their dependencies from outside, they don't know how they're being created and you can put your creation logic in one place only.
Making long story short: using DI lets us decouple components of our application. It makes our code more flexible and adaptable to different scenarios.

Multi-platform InputStream Alternative in Kotlin?

I’m looking for a multi-platform alternative to input streams. My concrete task is to fetch an encrypted file from a remote server via https and decrypt it on demand.
In Java land I would an implement InputStream which proxies the reads to the input stream from the https library. How can I do the same in kotlin targeting multiple platforms.
I see ktor returns an ByteReadChannel, but I don’t know which functions.
I’m lost and don’t know where to start. Thanks for your help in advance.
If the framework you are using does not provide you with a full-fledged InputStream implementation, the only chance left is to write your own. Much like what the ktor developers did: ByteReadChannel is just an abstraction of "reading bytes from a channel".
This abstraction lives in the common part and allows to write application and business logic around it.
The key to make this work in the context of a Kotlin Multiplatform project is, the actual implementation needs to be provided in the platform specific parts. The JVM specific code of the ktor project actually has an implementation that uses InputStream: InputStream.toByteReadChannel.
You certainly don't have to do it like your example from the ktor project and model everything down from byte channels up to file representations. If you want to leverage Kotlin framework classes, Sequences might be handy. This could look something like this:
// in common
interface FileFetcher {
fun fetch(): Sequence<Byte>
}
expect fun fileFetcher(source: String): FileFetcher
// in jvm
class JvmFileFetcher(val input: java.io.InputStream): FileFetcher {
override fun fetch(): Sequence<Byte> = input.readBytes().asSequence()
}
actual fun fileFetcher(source: String): FileFetcher {
val input = java.net.URL(source).openStream()
return JvmFileFetcher(input)
}
You would define an interface FileFetcher along with a factory function fileFetcher in the common part. By using the expect keyword on the fileFetcher function you need to provide platform-specific implementations for all target platforms you define. Use the FileFetcher interface in the common part to implement your logic (decrypting file contents etc.). See the documentation for Sequence for how to work with it.
Then implement the factory function for all platforms and use the actual keyword on them. You will then need to write platform-specific implementations of FileFetcher. My example shows how a JVM version of the FileFetcher interface.
The example is of course very basic and you probably would not want to do it exactly like this (at least some buffering would be needed, I guess). Also, within the JVM part you could also leverage your favorite networking/HTTP library easily.

Can anyone here explain the Kotlin/Native spinner app project structure in detail? Also the specifics on how different modules work

I would like to specifically know how the common module is used by the individual client modules. Which are the truly common parts that is shared by all the clients and the server.
Thank you.
This is easy. I suspect you're talking about Kotlin multiplatform modules.
Consider print and println.
In the common module we can expect a print function:
expect fun print(a: String)
But we don't know how was it implemented, because the common module doesn't know anything about Java's System.out, as well as JavaScript's console.
But the common module can expect such function that prints a String on screen, without providing an implementation.
Since we have print, we can implement println:
fun println(a: String) = print("$a\n")
All codes above are inside the common module.
And all you have to do is to to implement print for JVM/JS spererately.
For JVM:
actual fun print(a: String) = System.out.println(a)
For JS:
actual fun print(a: String) = console.log(a)
(Maybe) For Native:
actual fun print(a: String) = printf(a)
The three code blocks above are inside client modules.
Consider you've designed a data format, you have encoding and decoding code. Those codes are used in your Android device (JVM), your backend server (JVM), your frontend webpage (JS), your native app (Native).
You use Kotlin in all those sub projects but you want to write the encoder/decoder only once. Kotlin multiplatform module solves this probelm.
About the spinner app
It's not using the standard kotlin approach for creating multiplatform project. It's a trick on gradle.
There's a readResources (and randomInit as well, for osx/linux) function that implements differently on platforms but of the same signature, and gradle will decide which Kommon.kt should be compiled with the client projects.
readResources and randomInit should be marked as actual, and there should be a "common module" that has "expect"ed those two functions.
They didn't do this probably because Kotlin 1.2 (which brings stable multiplatform support) isn't out when KotlinConf holds.

Namespace and module confusion in typescript?

The official site of Typescript get me ask a question,
"Do we need to use namespace or not?".
The following quote explains the 2 things well:
It’s important to note that in TypeScript 1.5, the nomenclature has
changed. “Internal modules” are now “namespaces”. “External modules”
are now simply “modules”, as to align with ECMAScript 2015’s
terminology, (namely that module X { is equivalent to the
now-preferred namespace X {).
So, they suggest that TS team prefer namespace.
Further, it says we should use "namespace" to struct the internal module:
This post outlines the various ways to organize your code using
namespaces (previously “internal modules”) in TypeScript. As we
alluded in our note about terminology, “internal modules” are now
referred to as “namespaces”. Additionally, anywhere the module keyword
was used when declaring an internal module, the namespace keyword can
and should be used instead. This avoids confusing new users by
overloading them with similarly named terms.
The above quote is all from the Namespace section, and yes, it says again, but in a internal secnario.
but in the module section, one paragraph, says that:
Starting with ECMAScript 2015, modules are native part of the
language, and should be supported by all compliant engine
implementations. Thus, for new projects modules would be the
recommended code organization mechanism.
Does it mean that I don't need to bother with namespace, use module all along is the suggested way to develop?
Does it mean that I don't need to bother with namespace, use module all along is the suggested way to develop?
I wouldn't put it exactly that way... here's another paraphrase of what has happened. One upon a time, there were two terms used in Typescript
"external modules" - this was the TS analog to what the JS community called AMD (e.g. RequireJS) or CommonJS (e.g. NodeJS) modules. This was optional, for some people who write browser-based code only, they don't always bother with this, especially if they use globals to communicate across files.
"internal modules" - this is a hierarchical way of organising your variables/functions so that not everything is global. The same pattern exists in JS, it's when people organise their variables into objects/nested objects rather than having them all global.
Along came Ecmascript 2015 (a.k.a. ES6), which added a new formal, standard format that belonged in the "external modules" category. Because of this change, Typescript wanted to change the terminology to match the new Javascript standard (being that it likes to be a superset of Javascript, and tries its best to avoid confusion for users coming from Javascript). Thus, the switch of "external modules" being simplified to just "modules", and "internal modules" being renamed to "namespaces".
The quote you found here:
Starting with ECMAScript 2015, modules are native part of the language, and should be supported by all compliant engine implementations. Thus, for new projects modules would be the recommended code organization mechanism.
Is likely alluding to guidance for users who were not yet using (external) modules. To at least consider using it now. However, support for ES6 modules is still incomplete in that browsers as of May 2016 don't have built-in module loaders. So, you either have to add a polyfill (which handles it at runtime) like RequireJS or SystemJS, or a bundler (like browserify or webpack) that handles it at build time (before you deploy to your website).
So, would you ever use both modules (formerly "external modules") and namespaces? Absolutely - I use them both frequently in my codebases. I use (external) modules to organise my code files.
Namespaces in Typescript are extremely useful. Specifically, I use namespace declaration merging as a typesafe way to add extra properties to function objects themselves (a pattern often used in JS). In addition, while namespaces are a lot like regular object variables, you can hang subtypes (nested interfaces, classes, enums, etc.) off of their names.
Here is an example of a function with a property (very common in NodeJS libs):
function someUsefulFunction() {
// asynchronous version
return ...; // some promise
}
namespace someUsefulFunction {
export function sync() {
// synchronous version
}
}
This allows for consumers to do this common NodeJS pattern:
// asynchronous consumer
someUsefulFunction()
.then(() => {
// ...
});
// synchronous consumer
someUsefulFunction.sync();
Similarly, say you have an API that takes in an options object. If that options type is specific to that API,
function myFunc(options?: myFunc.Options) {
// ...
}
namespace myFunc {
export interface Options {
opt1?: number;
opt2?: boolean;
opt3?: string;
}
}
In that case, you don't have to pollute a larger namespace (say whole module scope) with the type declaration for the options.
Hope this helps!

Creating an Objective-C API

I have never made an API in objective-c, and need to do this now.
The "idea" is that I build an API which can be implemented into other applications. Much like Flurry, only for other purposes.
When starting the API, an username, password and mode should be entered. The mode should either be LIVE or BETA (I guess this should be an NSString(?)), then afterwards is should be fine with [MyAPI doSomething:withThisObject]; ect.
So to start it [MyAPI username:#"Username" password:#"Password" mode:#"BETA"];
Can anyone help me out with some tutorials and pointer on how to learn this best?
It sounds like what you want to do is build a static library. This is a compiled .a file containing object code that you'll distribute to a client along with a header file containing the interface. This post is a little outdated but has some good starting points. Or, if you don't mind giving away your source code, you could just deliver a collection of source files to your client.
In terms of developing the API itself, it should be very similar to the way you'd design interfaces and implementations of Objective-C objects in your own apps. You'll have a MyAPI class with functions for initialization, destruction, and all the functionality you want. You could also have multiple classes with different functionality if the interface is complex. Because you've capitalized MyAPI in your code snippet, it looks like you want to use it by calling the class rather than an instance of the class - which is a great strategy if you think you'll only ever need one instance. To accomplish this you can use the singleton pattern.
Because you've used a username and password, I imagine your API will interface with the web internally. I've found parsing JSON to be very straightforward in Objective-C - it's easy to send requests and get information from a server.
Personally I would use an enum of unsigned ints rather than a NSString just because it simplifies comparisons and such. So you could do something like:
enum {
MYAPI_MODE_BETA,
MYAPI_MODE_LIVE,
NUM_MYAPI_MODES
};
And then call:
[MyAPI username:#"Username" password:#"Password" mode:MYAPI_MODE_BETA];
Also makes it easy to check if they've supplied a valid mode. (Must be less than NUM_MYAPI_MODES.)
Good luck!