--- a/application/davcontroller.c Sun Oct 06 18:43:06 2024 +0200 +++ b/application/davcontroller.c Sun Oct 20 21:24:13 2024 +0200 @@ -34,6 +34,7 @@ #include "config.h" #include "system.h" +#include "common/context.h" #include <libidav/config.h> #include <libidav/utils.h> @@ -48,6 +49,8 @@ doc->navstack_pos = 0; doc->dav_queue = ui_threadpool_create(1); + + doc->res_open_inprogress = cxHashMapCreate(ctx->allocator, CX_STORE_POINTERS, 4); doc->path = ui_string_new(ctx, "path"); doc->resources = ui_list_new(ctx, "reslist"); @@ -198,6 +201,64 @@ } } +void davbrowser_open_resource(UiObject *ui, DavBrowser *browser, DavResource *res) { + char *url = util_concat_path(browser->sn->base_url, res->path); + void *x = cxMapGet(browser->res_open_inprogress, url); + free(url); + if(x) { + return; // open resource already in progress + } + + DavResourceViewType type = DAV_RESOURCE_VIEW_PROPERTIES; + if(res->iscollection) { + // default type + } else if(res->contenttype) { + cxstring contenttype = cx_str(res->contenttype); + if(cx_strprefix(contenttype, CX_STR("text/"))) { + type = DAV_RESOURCE_VIEW_TEXT; + } else if(cx_strprefix(contenttype, CX_STR("image/"))) { + type = DAV_RESOURCE_VIEW_IMAGE; + } else if(cx_strprefix(contenttype, CX_STR("application/"))) { + if(cx_strsuffix(contenttype, CX_STR("json"))) { + type = DAV_RESOURCE_VIEW_TEXT; + } else if(cx_strsuffix(contenttype, CX_STR("/xml"))) { + type = DAV_RESOURCE_VIEW_TEXT; + } else if(cx_strsuffix(contenttype, CX_STR("+xml"))) { + type = DAV_RESOURCE_VIEW_TEXT; + } else if(cx_strsuffix(contenttype, CX_STR("/xml"))) { + type = DAV_RESOURCE_VIEW_TEXT; + } + } + } else { + cxstring path = cx_str(res->path); + if(cx_strsuffix(path, CX_STR(".png"))) { + type = DAV_RESOURCE_VIEW_IMAGE; + } else if(cx_strsuffix(path, CX_STR(".jpg"))) { + type = DAV_RESOURCE_VIEW_IMAGE; + } else if(cx_strsuffix(path, CX_STR(".jpeg"))) { + type = DAV_RESOURCE_VIEW_IMAGE; + } else if(cx_strsuffix(path, CX_STR(".tif"))) { + type = DAV_RESOURCE_VIEW_IMAGE; + } else if(cx_strsuffix(path, CX_STR(".tiff"))) { + type = DAV_RESOURCE_VIEW_IMAGE; + } else if(cx_strsuffix(path, CX_STR(".webp"))) { + type = DAV_RESOURCE_VIEW_IMAGE; + } else if(cx_strsuffix(path, CX_STR(".bmp"))) { + type = DAV_RESOURCE_VIEW_IMAGE; + } else if(cx_strsuffix(path, CX_STR(".gif"))) { + type = DAV_RESOURCE_VIEW_IMAGE; + } else if(cx_strsuffix(path, CX_STR(".txt"))) { + type = DAV_RESOURCE_VIEW_TEXT; + } else if(cx_strsuffix(path, CX_STR(".md"))) { + type = DAV_RESOURCE_VIEW_TEXT; + } else if(cx_strsuffix(path, CX_STR(".xml"))) { + type = DAV_RESOURCE_VIEW_TEXT; + } + } + + dav_resourceviewer_new(browser, res->path, type); +} + void davbrowser_add2navstack(DavBrowser *browser, const char *base, const char *path) { if (browser->navstack_enabled) { for (int i = 0; i < browser->navstack_pos; i++) { @@ -1152,3 +1213,102 @@ void davbrowser_newfile(UiObject *ui, DavBrowser *browser, const char *name) { davbrowser_create_resource(ui, browser, name, FALSE); } + + + +DavResourceViewer* dav_resourceviewer_create(DavSession *sn, const char *path, DavResourceViewType type) { + DavResourceViewer *doc = ui_document_new(sizeof(DavResourceViewer)); + UiContext *ctx = ui_document_context(doc); + doc->ctx = ctx; + + doc->sn = dav_session_clone(sn); + doc->path = strdup(path); + doc->type = type; + + doc->tabview = ui_int_new(ctx, "tabview"); + doc->loading = ui_int_new(ctx, "loading"); + doc->message = ui_string_new(ctx, "message"); + + doc->text = ui_text_new(ctx, "text"); + doc->image = ui_generic_new(ctx, "image"); + + doc->properties = ui_list_new(ctx, "properties"); + + return doc; +} + +static char* gen_tmp_download_filename(const char *name) { + char *dir = ui_getappdir(); + + unsigned char rd[8]; + memset(rd, 0, 8); + dav_rand_bytes(rd, 8); + char *hex = util_hexstr(rd, 8); + cxmutstr tmp = cx_asprintf("%sdownload-%s-%s", dir, name, hex); + return tmp.ptr; +} + +static int jobthr_resourceviewer_load(void *data) { + DavResourceViewer *doc = data; + + DavResource *res = dav_resource_new(doc->sn, doc->path); + doc->error = dav_load(res); + if(!doc->error) { + doc->current = res; + + if(res->contentlength < DAV_RESOURCEVIEWER_PREVIEW_MAX_SIZE) { + if(doc->type == DAV_RESOURCE_VIEW_TEXT) { + doc->text_content = cxBufferCreate(NULL, res->contentlength, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); + int err = dav_get_content(res, doc->text_content, (dav_write_func)cxBufferWrite); + cxBufferPut(doc->text_content, 0); + if(err) { + doc->error = err; + doc->message_str = "Cannot load content"; // TODO: better message + } + } else if(doc->type == DAV_RESOURCE_VIEW_IMAGE) { + char *tmp = gen_tmp_download_filename(res->name); + FILE *f = fopen(tmp, "w"); + if(f) { + int err = dav_get_content(res, f, (dav_write_func)fwrite); + if(!err) { + doc->tmp_file = tmp; + } else { + free(tmp); + } + fclose(f); + } else { + free(tmp); + } + } + } else { + // TODO: add file too large message + } + } else { + doc->message_str = "Cannot load properties"; // TODO: better message + dav_resource_free(res); + } + + return 0; +} + +static void resourceviewer_load_finished(UiEvent *event, void *data) { + DavResourceViewer *doc = data; + + if(doc->type == DAV_RESOURCE_VIEW_TEXT) { + ui_set(doc->text, doc->text_content->space); + } else if(doc->type == DAV_RESOURCE_VIEW_IMAGE) { + ui_image_load_file(doc->image, doc->tmp_file); + unlink(doc->tmp_file); + } + + ui_set(doc->tabview, 1); +} + +void dav_resourceviewer_load(UiObject *ui, DavResourceViewer *res) { + ui_set(res->loading, 1); + ui_set(res->message, "Loading..."); + ui_set(res->tabview, 0); + + ui_job(ui, jobthr_resourceviewer_load, res, resourceviewer_load_finished, res); +} +