Open fairking opened 2 years ago
Thank you for your attention. Embedding webview into same window is hard. So full-featured webview widget is like impossible. But you can look up vwebui if you can use webview inside another window. Also you can port your PWA application with Vebview.JS. But sad to say these solutions won't work inside Android.
Thanks for your reply, I hope there will be some solution to this, and it could be a deal breaker to bring more popularity to v language. I have several projects (Web/Electron) but there is no way to get them to mobile platforms, having a strong backend and native support. I am monitoring tauri, looks like they are currently working on the mobile support.
Why I am convinced to PWA over native UI:
The way how I am used to implement such applications: The backend has services (DI) and expose those services to the public as an OpenAPI scheme. For web application such services consumed via http, for desktop/mobile app such services consumed via js interop (not localhost). During development the codegen uses API scheme to generate such services in JS/TS. All communication including native support happens via the API services (communication between frontend and backend using services). Example:
Another simple example of the implementation:
entities\article.v
struct Article {
id int [primary; sql: serial]
title string
text string
}
models\article.v
struct IdModel {
id int [required]
}
struct ArticleModel {
id int
title string
text string
}
struct CreateArticleModel {
title string [required; maxlength: 50]
text string
}
struct UpdateArticleModel { ... }
struct PublishArticleModel { ... }
...
services\article_service.v
[api]
struct ArticleService {
db DbService // Injected service or repository
}
[api]
pub fn (article_service &ArticleService) get(query IdModel) ArticleModel {
result = sql article_service.db {
select from Article where id = $query.id
}
return result.map<ArticleModel>()
}
[api]
pub fn (article_service &ArticleService) create(form CreateArticleModel ) IdModel {
form.validate_or_throw() or { ValidationError };
result = sql article_service.db {
insert into Article (id, title, text) set ($form.id, $form.title, $form.text)
} or { DbError }
return IdModel { result }
}
codegen generates the following js/ts (based on open api scheme, eg. https://github.com/Manweill/swagger-axios-codegen):
services.ts
export class IdModel {
'id'?: number;
constructor(data: undefined | any = {}) {
this['id'] = data['id'];
}
public static validationModel = { id: { required: true } };
}
.. all other models
export class ArticleService {
static get(params: { body?: IdModel; } = {} as any, options: IRequestOptions = {}): Promise<ArticleModel> {
return new Promise((resolve, reject) => {
let url = basePath + '/ArticleService/Get';
const configs: IRequestConfig = getConfigs('post', 'application/json', url, options);
let data = params.body;
configs.data = data;
if (web) {
axios(configs, resolve, reject);
} else if (mobile) {
js_interop(configs, resolve, reject);
} else {
throw Error("platform not supported");
}
});
}
... etc other services
}
Example of js interop in .NET: https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/
I am aware of the following cons:
So what is actually required is a WebView, and the ability to communicate between the WebView and the backend (in this case mui). Nothing else. It is easy as that.
I can try to create WebView window with webview/webview. This library has good cross-platform support, uses system-webviews but it requires C++11 minimum (and C++17 for Windows). If I can make working the library with V (without very complicated compile steps), I will add a WebView window into mui for only desktop platforms (for now).
I got working webviews on Linux and Windows. That's not have API except C functions that provided by webview library for now, however i will write V-compatible functions (also that could be include functions not provided from C library like resize or move, but that is not first goal). You can follow updates from WebView branch. Screenshot from WebView Example: Linux (Ubuntu): Windows:
Cool. Thank you. 👍
As I can see there are two features required (if not already there) as a minimum to get hybrid app working:
wwwroot
v.call_js({ json }
and js.call_v({ json })
)I will test it this week.
After latest commit at webview branch
Local assets (js, css, images) consumed by WebView, something like wwwroot
You can load html files with load_html_file
function.
Limitations:
CORS
and/or other policies./
inside path, that will refer to /
(C:/
for Windows). And your assets will not load. You can use ./
inside all paths to solve it.V <-> JS communication (v.call_js({ json } and js.call_v({ json }))
my_return
) and run the code (ex. webview.eval("my_return(2+4);")
)important_v_fn
) and you can call them from JavaScript code. (ex. important_v_fn("Param1","Param2").then(console.log)
)You can browse example code at webview branch.
👍 I am going to test it now.
You can not call V function directly from JavaScript (that needed by security reasons).
Every hybrid app has such ability. It is not like js can eval any v code in the backend. It is just some kind of a channel to get/post information from/to the backend, same as it was a http request. Eg.:
in v:
app_data.webview.register_handler('my_handler', handler) // registers a `my_handler` method in webview
fn handler(message string) ?string {
request := deserialize<ServiceRequest>(message)
mut result = ''
if request.route.starts_with('/Articles') {
srv := ArticleService{ db }
if request.route.starts_with('/Articles/Get') {
params := deserialize<GetArticleQuery>(request.body)
result = serialize<ArticleModel>(srv.get(params)?) or { error('could not execute service $data.route') }
} else {
error('could not find route $data.route')
}
} else {
error('could not find route $data.route')
}
return result
}
// somewhere in my code
struct ServiceRequest {
pub:
route string
body string
}
module articles
struct GetArticleQuery {
pub:
id int
}
struct ArticleModel {
pub:
id int
title string
text string
}
struct ArticleService {
db DatabaseService
}
pub fn (a ArticleService) get(q GetArticleQuery) ArticleModel {
return a.db.query<ArticleModel>(select * from articles where id = $q.id)
}
and then js:
<script>
function load_article(article_id) {
call_v("my_handler", "{ route: '/Articles/Get', body: { id: article_id } }") // returns Promise
.then(result => {
article_page.form = result.data;
}).catch(error => {
alert("Error: " + error);
});
}
</script>
Same approach with Scan Barcode
example. You can even build a file explorer in this way.
You can look at this as an example: https://tauri.app/v1/guides/features/command
It uses file protocol instead of localhost
👍 yes, no localhost, it will be over-complicated and not native.
If you use / inside path, that will refer to / (C:/ for Windows).
I guess the base path can be used. Or as an alternative some protocol mui://my_script.js
pointing to the www
root folder required.
I made a basic Articles example. This is not use any db or anything but it's good to explain V-JavaScript inter-op. Also this example written by vanilla JavaScript but could be used Vue.JS or another JavaScript library to make the application more powerful.
You can browse the code.
You can browse the code.
I tried to to run the webview example but I am getting an error "cannot import module "malisipi.mui.webview" (not found)" Do you know how to solve it?
btw, before I have run: v install https://github.com/malisipi/mui
.
Do you know how to solve it?
v installs default branch so you must install yourself,
cd ~/.vmodules/malisipi
rm -rdf mui
git clone https://github.com/malisipi/mui --branch webview
Also you must need to compile webview.o
before use module.
So open terminal in ~/.vmodules/malisipi/mui/webview
and run build_webview_for_
PS: Also if you use Windows, compiling example is could be too challenging.
You need a few h file from W10 SDK. But you can not find/download without downloading entire SDK from Microsoft.
You must to set set W10_SDK=/path/to/sdk
before compiling webview.o
.
Also you need to have gcc to compile. TCC won't compile the library causes error that i can not understand why. So you need to gcc. For using gcc, v -cc gcc ...
Maybe I have missed something, but I got the following error:
C:\Code\mui\examples\webview\webview_example>v -cc gcc run webview_example.v
C:\Users\Admin\.vmodules\malisipi\mui\webview\webview.obj not found, building it (with msvc)...
builder error: MSVC cannot link against a dll (`#flag -l WebView2Loader.dll`)
C:\Code\mui\examples\webview\webview_example>
this is how I built the webview (copied from my terminal):
C:\Users\Admin\.vmodules\malisipi\mui\webview>set W10_SDK=C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0
C:\Users\Admin\.vmodules\malisipi\mui\webview>PATH %PATH%;C:\mingw64\bin
C:\Users\Admin\.vmodules\malisipi\mui\webview>build_webview_for_windows
C:\Users\Admin\.vmodules\malisipi\mui\webview>g++ -c C:\Users\Admin/.vmodules/malisipi/mui/webview/webview/webview.cc -lstdc++ -shared -static -std=c++17 -I C:\Users\Admin/.vmodules/malisipi/mui/webview/webview2/build/native/include -I "C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0/winrt/" -lWebView2Loader.dll -lole32 -lshell32 -lshlwapi -luser32 -o C:\Users\Admin/.vmodules/malisipi/mui/webview/webview.o
C:\Users\Admin\.vmodules\malisipi\mui\webview>
Looks like webview.o
created correctly.
But i guess v can not found gcc and so tried to use msvc, and failed. Did you add gcc to path before compiling v-example.
If that not works, please send v -showcc -cc gcc ...
output. This output have infos like which compiler used or which flags used while compiling.
Also, if you see a error like that while running application. Code execution cannot continue because WebView2Loader.dll was not found. Reinstalling the program may fix this problem.
. This is normal, you must copy ~/.vmodules/webview/webview2/runtimes/win-
/native/WebView2Loader.dll
into your app directory.
These what I have:
C:\Code\mui\examples\webview>gcc
'gcc' is not recognized as an internal or external command,
operable program or batch file.
C:\Code\mui\examples\webview>set W10_SDK=C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0
C:\Code\mui\examples\webview>PATH %PATH%;C:\mingw64\bin
C:\Code\mui\examples\webview>gcc
gcc: fatal error: no input files
compilation terminated.
C:\Code\mui\examples\webview>v -showcc -cc gcc run webview_example.v
v expects that `webview_example.v` exists, but it does not
C:\Code\mui\examples\webview>cd webview_example
C:\Code\mui\examples\webview\webview_example>v -showcc -cc gcc run webview_example.v
> C compiler cmd: "gcc" "@C:\Users\Admin\AppData\Local\Temp\v_0\webview_example.9499648542930297532.tmp.c.rsp"
> C compiler response file "C:\Users\Admin\AppData\Local\Temp\v_0\webview_example.9499648542930297532.tmp.c.rsp":
-std=c99 -D_DEFAULT_SOURCE "C:\\Users\\Admin\\.vmodules\\cache\\28\\281ce86301abbcad64e66a688c6fcec7.module.builtin.o" "C:\\Users\\Admin\\.vmodules\\cache\\7e\\7e3c4e2c5f7170f871dbb70ff5415fae.module.json.o" "C:\\Users\\Admin\\.vmodules\\cache\\9d\\9d6a7c3263b5e61122c2cef48f3047cb.module.stbi.o" "C:\\Users\\Admin\\.vmodules\\cache\\2a\\2a1e94ac4ac24b07238d4d186bdbed9b.module.malisipi.mui.webview.o" -o "C:\\Code\\mui\\examples\\webview\\webview_example\\webview_example.exe" -Wl,-stack=16777216 -Werror=implicit-function-declaration -D GC_NOT_DLL=1 -D GC_WIN32_THREADS=1 -D GC_BUILTIN_ATOMIC=1 -D GC_THREADS=1 -D SOKOL_GLCORE33 -D SOKOL_NO_ENTRY -D SOKOL_WIN32_FORCE_MAIN -I "C:\\Code\\v\\thirdparty\\libgc\\include" -I "C:\\Code\\v\\thirdparty\\cJSON" -I "C:\\Code\\v\\thirdparty\\stb_image" -I "C:\\Code\\v\\thirdparty\\fontstash" -I "C:\\Code\\v\\thirdparty\\sokol" -I "C:\\Code\\v\\thirdparty\\sokol\\util" -L "C:\\Users\\Admin\\.vmodules\\malisipi\\mui\\webview\\webview2\\build\\native\\x64" -I "C:\\Users\\Admin\\.vmodules\\malisipi\\mui\\webview\\webview2\\build\\native\\include" -static -I "C:\\Code\\mui\\examples\\webview\\webview_example\\webview\\" -I "C:\\Code\\v\\thirdparty\\vschannel" C:\\Users\\Admin\\.vmodules\\malisipi\\mui/tinyfiledialogs/tinyfiledialogs.c "C:\\Users\\Admin\\AppData\\Local\\Temp\\v_0\\webview_example.9499648542930297532.tmp.c" -municode -ldbghelp -lgdi32 -ladvapi32 -lWebView2Loader.dll -lole32 -lshell32 -lshlwapi -luser32 -lstdc++ -lgdi32 -lws2_32 -lcrypt32 -lsecur32 -luser32 -lurlmon -lcomdlg32
C:\Code\mui\examples\webview\webview_example>v -cc gcc run webview_example.v
C:\Code\mui\examples\webview\webview_example>
On executing the v -showcc -cc gcc run webview_example.v
or v -cc gcc run webview_example.v
nothing happens. No window appears. Should I need to do anything else?
But these time that error disappeared.
Your executables created correctly according V compiler logs, so should work fine and i can not recognize the bug.
~/.vmodules/malisipi/mui/examples/webview/articles.v
)~/.vmodules/malisipi/mui/examples/demo.v
)
If first example not works, you could be not have Microsoft Edge Webview 2 Runtime (but i guess you are using Windows 11 (according your uploaded folder photo) and this runtime come pre-installed.)
If second example not works, your OpenGL version not compatible with MUI.
Same with articles.v
, no window, compilation goes through silently.
For demo.v
I have the following error:
Microsoft Windows [Version 10.0.22000.1165]
(c) Microsoft Corporation. All rights reserved.
C:\Code\mui\examples>v run demo.v
builder error: 'commdlg.h' not found
C:\Code\mui\examples>
Same with articles.v, no window, compilation goes through silently.
If a executable was created, can you upload?
v run demo.v
I can reproduce the bug, i will fix it.
Ok, I get the demo app working with the command v -cc gcc run demo.v
. It took about a minute to run. However if I try to add a new record it says "Successfully Completed", but no record shown on the list after that. Tried it several times.
However the v -cc gcc run articles.v
is not working (no errors, empty terminal).
Do we have any error logs somewhere?
Do we have any error logs somewhere?
Sorry, i haven't created any log system.
However the v -cc gcc run articles.v is not working.
Does this command create any executable? If yes, can you attach executable in your comment.
Does this command create any executable? If yes, can you attach executable in your comment.
Cannot see anything in the current folder:
Or is it located somewhere else?
Run without run
keyword v -cc gcc articles.v
Also the issue is about like webview, can you check out you have microsoft webview2 runtime. If you not, you can download from Microsoft
Also the issue is about like webview, can you check out you have microsoft webview2 runtime. If you not, you can download from Microsoft
ok, the
v -cc gcc articles.v
did the work. please find it here.
This example works (your compiled) on me. Did you copy WebView2Loader.dll to your app directory?
You should copy ~/.vmodules/webview/webview2/runtimes/win-
/native/WebView2Loader.dll
into your app directory.
You should copy
WebView2Loader.dll
into your app directory.
Thanks, now everything is working. Would be nice to write a doc how to build the mui app. 👍
Would be nice to write a doc how to build the mui app.
You're right. I will write a documentation before merge webview with main branch.
I will write a vuejs example and see how it works by the end of this week. I can fork your branch, so it will come back as an example if you are happy with that. Later we can automate the build a little bit, so no hassle with installing and setting up the environment for build.
I will write a vuejs example and see how it works by the end of this week. I can fork your branch, so it will come back as an example if you are happy with that.
Thanks for dealing with the repo. I will be grateful for your pull request. If you have a problem with project, you can ask here.
Later we can automate the build a little bit, so no hassle with installing and setting up the environment for build.
That is good idea, that could be hard to make compatible with all operating systems. However it is worth to make.
So as far as I can see the custom uri scheme is required in order to serve local files. This will be the best and most secure approach accessing local asset files by the webview. I will keep working on it https://github.com/fairking/mui/tree/vuejs_app_example
Also I asked WebView guys why it is not available out of the box: https://github.com/webview/webview/issues/851
I understand why we need custom uri scheme really. I will watch https://github.com/webview/webview/issues/851 for now. If their response is positive, i will wait their implementation this feature. Else, i will patch webview again to get that.
Also, your example looks good especially for peoples wants use web & v together.
Looks to be a great project. Hope that it does not fall off from being sidetracked or distracted with webview or porting of PWA, and can maintain a balance. Not everyone is coming from or wants to go in that direction.
Looks to be a great project. Hope that it does not fall off from being sidetracked or distracted with webview or porting of PWA, and can maintain a balance. Not everyone is coming from or wants to go in that direction.
As a senior backend developer I can understand you. But it depends what are you going to build. Simple apps, tools, utils are best with native UI, no doubt. However more complex and constantly changing frontend requires html/js. If you want to find a good graphic designer or UX guy, they are all HTML/JS duck-typing guys. Why? Because they are artists, they don't like strong type languages. And during my long career I had to accept that :-)
Just simple example. As a subscription manager and join membership app (web and android) we have to build a new unique app for every new customer (1 month of work). Please note, the API (backend) had minimal or no changes. If we go with the native approach, it will take at least 3 months instead. The second issue, we didn't have backend developers too much in which case native UI requires.
But if it comes to scan barcode, NFC, camera, files and many other features the webview lack of, the native tools are very useful as well in such situations.
...depends what are you going to build. Simple apps, tools, utils are best with native UI, no doubt. However more complex and constantly changing frontend requires html/js.
First, let us acknowledge that it's fantastic what Malisipi has done, and that his project can accommodate both.
It is of course a matter of perspective, as to which people may prefer, native UI or HTML/JS. There are those that prefer native UIs too. It's not just one over the other. I'm just pointing out that originally it appears the project was not about webview or the porting of PWA, but native UIs and has various related items on the to-do list. Luckily, Malisipi was so far along that he could do both, and its great that it has gone that way.
Yes, I agree with what is going on here and the direction MUI is generally taking. Much appreciated @malisipi !
I came here only to emphasize that the most successful apps from small dev teams use a hybrid strategy - they build part of the GUI (yes, not just backend!) in native technology (here either Android Java or V bindings to the Android Java API) and the other part from one (or multiple!) webviews.
Note the native GUI parts can arbitrarily overlap with webviews (with transparency both ways, events coming through both ways, and other goodies) and thus one can construct a really natively-feeling apps (relatively low latency, theme-aware, platform-specific gesture recognition, ...) while maintaining the rapid development pace.
This is awesome. Is there any plans to implement some kind of WebView, so we can port web SPA/PWA applications, the same way how tauri is doing? I am particularly interesting in Android. And of course I can rewrite my backend in vlang. ;-)