diff --git a/.gitignore b/.gitignore index 8d52d1d..287822c 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,7 @@ CMakeUserPresets.json /_CPack_Packages debug_log* debug_* +.vscode/tasks.json +/.vscode +data/session.json +.vscode/ diff --git a/CMakeLists.txt b/CMakeLists.txt index c88e971..b3d4223 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -241,6 +241,70 @@ if(WIN32) endif() endif() +# Linux: include SDK shared libraries (.so) and resources +if(UNIX AND NOT APPLE) + file(GLOB ULTRALIGHT_SOS "${ULTRALIGHT_SDK_ROOT}/lib/*.so*") + list(LENGTH ULTRALIGHT_SOS _so_count) + if(_so_count GREATER 0) + install(FILES ${ULTRALIGHT_SOS} DESTINATION ${INSTALL_DIR_NAME}) + endif() + + # Also check for libraries in bin directory (some SDK layouts) + file(GLOB ULTRALIGHT_BIN_SOS "${ULTRALIGHT_SDK_ROOT}/bin/*.so*") + list(LENGTH ULTRALIGHT_BIN_SOS _bin_so_count) + if(_bin_so_count GREATER 0) + install(FILES ${ULTRALIGHT_BIN_SOS} DESTINATION ${INSTALL_DIR_NAME}) + endif() + + # ICU data files (check multiple possible locations) + file(GLOB ICU_FILES_LIB "${ULTRALIGHT_SDK_ROOT}/lib/ICU/icudt*.dat" "${ULTRALIGHT_SDK_ROOT}/lib/ICU/cacert.pem") + file(GLOB ICU_FILES_BIN "${ULTRALIGHT_SDK_ROOT}/bin/ICU/icudt*.dat" "${ULTRALIGHT_SDK_ROOT}/bin/ICU/cacert.pem") + file(GLOB ICU_FILES_RES "${ULTRALIGHT_SDK_ROOT}/resources/icudt*.dat" "${ULTRALIGHT_SDK_ROOT}/resources/cacert.pem") + set(ICU_FILES ${ICU_FILES_LIB} ${ICU_FILES_BIN} ${ICU_FILES_RES}) + list(LENGTH ICU_FILES _icu_count) + if(_icu_count GREATER 0) + install(FILES ${ICU_FILES} DESTINATION ${INSTALL_DIR_NAME}/assets/resources) + endif() + + # Include resources directory if it exists + if(EXISTS "${ULTRALIGHT_SDK_ROOT}/resources") + install(DIRECTORY "${ULTRALIGHT_SDK_ROOT}/resources/" DESTINATION ${INSTALL_DIR_NAME}/assets/resources + FILES_MATCHING PATTERN "*" PATTERN "*.dat" PATTERN "*.pem" PATTERN "*.bin") + endif() +endif() + +# macOS: include SDK dynamic libraries (.dylib) and resources +if(APPLE) + file(GLOB ULTRALIGHT_DYLIBS "${ULTRALIGHT_SDK_ROOT}/lib/*.dylib*") + list(LENGTH ULTRALIGHT_DYLIBS _dylib_count) + if(_dylib_count GREATER 0) + install(FILES ${ULTRALIGHT_DYLIBS} DESTINATION ${INSTALL_DIR_NAME}) + endif() + + # Also check for libraries in bin directory (some SDK layouts) + file(GLOB ULTRALIGHT_BIN_DYLIBS "${ULTRALIGHT_SDK_ROOT}/bin/*.dylib*") + list(LENGTH ULTRALIGHT_BIN_DYLIBS _bin_dylib_count) + if(_bin_dylib_count GREATER 0) + install(FILES ${ULTRALIGHT_BIN_DYLIBS} DESTINATION ${INSTALL_DIR_NAME}) + endif() + + # ICU data files (check multiple possible locations) + file(GLOB ICU_FILES_LIB "${ULTRALIGHT_SDK_ROOT}/lib/ICU/icudt*.dat" "${ULTRALIGHT_SDK_ROOT}/lib/ICU/cacert.pem") + file(GLOB ICU_FILES_BIN "${ULTRALIGHT_SDK_ROOT}/bin/ICU/icudt*.dat" "${ULTRALIGHT_SDK_ROOT}/bin/ICU/cacert.pem") + file(GLOB ICU_FILES_RES "${ULTRALIGHT_SDK_ROOT}/resources/icudt*.dat" "${ULTRALIGHT_SDK_ROOT}/resources/cacert.pem") + set(ICU_FILES ${ICU_FILES_LIB} ${ICU_FILES_BIN} ${ICU_FILES_RES}) + list(LENGTH ICU_FILES _icu_count) + if(_icu_count GREATER 0) + install(FILES ${ICU_FILES} DESTINATION ${INSTALL_DIR_NAME}/assets/resources) + endif() + + # Include resources directory if it exists + if(EXISTS "${ULTRALIGHT_SDK_ROOT}/resources") + install(DIRECTORY "${ULTRALIGHT_SDK_ROOT}/resources/" DESTINATION ${INSTALL_DIR_NAME}/assets/resources + FILES_MATCHING PATTERN "*" PATTERN "*.dat" PATTERN "*.pem" PATTERN "*.bin") + endif() +endif() + # Post-build: copy assets and runtime files next to the exe for running from build dir if(WIN32) add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD @@ -262,6 +326,108 @@ if(WIN32) ) endif() +# Post-build: copy assets and runtime files for Linux +if(UNIX AND NOT APPLE) + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/assets" "$/assets" + ) + # Copy shared libraries from lib directory + file(GLOB _linux_sos "${ULTRALIGHT_SDK_ROOT}/lib/*.so*") + foreach(_so ${_linux_sos}) + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_so}" "$/" + ) + endforeach() + # Also check bin directory + file(GLOB _linux_bin_sos "${ULTRALIGHT_SDK_ROOT}/bin/*.so*") + foreach(_so ${_linux_bin_sos}) + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_so}" "$/" + ) + endforeach() + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory "$/assets/resources" + ) + # Copy ICU files from various possible locations + if(EXISTS "${ULTRALIGHT_SDK_ROOT}/bin/ICU/icudt67l.dat") + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ULTRALIGHT_SDK_ROOT}/bin/ICU/icudt67l.dat" "$/assets/resources/icudt67l.dat" + ) + elseif(EXISTS "${ULTRALIGHT_SDK_ROOT}/lib/ICU/icudt67l.dat") + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ULTRALIGHT_SDK_ROOT}/lib/ICU/icudt67l.dat" "$/assets/resources/icudt67l.dat" + ) + elseif(EXISTS "${ULTRALIGHT_SDK_ROOT}/resources/icudt67l.dat") + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ULTRALIGHT_SDK_ROOT}/resources/icudt67l.dat" "$/assets/resources/icudt67l.dat" + ) + endif() + if(EXISTS "${ULTRALIGHT_SDK_ROOT}/bin/ICU/cacert.pem") + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ULTRALIGHT_SDK_ROOT}/bin/ICU/cacert.pem" "$/assets/resources/cacert.pem" + ) + elseif(EXISTS "${ULTRALIGHT_SDK_ROOT}/lib/ICU/cacert.pem") + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ULTRALIGHT_SDK_ROOT}/lib/ICU/cacert.pem" "$/assets/resources/cacert.pem" + ) + elseif(EXISTS "${ULTRALIGHT_SDK_ROOT}/resources/cacert.pem") + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ULTRALIGHT_SDK_ROOT}/resources/cacert.pem" "$/assets/resources/cacert.pem" + ) + endif() +endif() + +# Post-build: copy assets and runtime files for macOS +if(APPLE) + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/assets" "$/assets" + ) + # Copy dynamic libraries from lib directory + file(GLOB _macos_dylibs "${ULTRALIGHT_SDK_ROOT}/lib/*.dylib*") + foreach(_dylib ${_macos_dylibs}) + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_dylib}" "$/" + ) + endforeach() + # Also check bin directory + file(GLOB _macos_bin_dylibs "${ULTRALIGHT_SDK_ROOT}/bin/*.dylib*") + foreach(_dylib ${_macos_bin_dylibs}) + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_dylib}" "$/" + ) + endforeach() + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory "$/assets/resources" + ) + # Copy ICU files from various possible locations + if(EXISTS "${ULTRALIGHT_SDK_ROOT}/bin/ICU/icudt67l.dat") + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ULTRALIGHT_SDK_ROOT}/bin/ICU/icudt67l.dat" "$/assets/resources/icudt67l.dat" + ) + elseif(EXISTS "${ULTRALIGHT_SDK_ROOT}/lib/ICU/icudt67l.dat") + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ULTRALIGHT_SDK_ROOT}/lib/ICU/icudt67l.dat" "$/assets/resources/icudt67l.dat" + ) + elseif(EXISTS "${ULTRALIGHT_SDK_ROOT}/resources/icudt67l.dat") + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ULTRALIGHT_SDK_ROOT}/resources/icudt67l.dat" "$/assets/resources/icudt67l.dat" + ) + endif() + if(EXISTS "${ULTRALIGHT_SDK_ROOT}/bin/ICU/cacert.pem") + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ULTRALIGHT_SDK_ROOT}/bin/ICU/cacert.pem" "$/assets/resources/cacert.pem" + ) + elseif(EXISTS "${ULTRALIGHT_SDK_ROOT}/lib/ICU/cacert.pem") + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ULTRALIGHT_SDK_ROOT}/lib/ICU/cacert.pem" "$/assets/resources/cacert.pem" + ) + elseif(EXISTS "${ULTRALIGHT_SDK_ROOT}/resources/cacert.pem") + add_custom_command(TARGET Ultralight-WebBrowser POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ULTRALIGHT_SDK_ROOT}/resources/cacert.pem" "$/assets/resources/cacert.pem" + ) + endif() +endif() + # CPack (global scope) set(WEBBROWSER_VERSION "dev" CACHE STRING "WebBrowser version to use in package names (defaults to 'dev')") set(CPACK_PACKAGE_NAME "Ultralight-WebBrowser") diff --git a/assets/settings_catalog.json b/assets/settings_catalog.json index 3e0c7be..bded339 100644 --- a/assets/settings_catalog.json +++ b/assets/settings_catalog.json @@ -223,5 +223,21 @@ "category": "developer", "note": null, "default": false + }, + { + "key": "restore_session_on_startup", + "name": "Restore previous session", + "description": "Reopen tabs from your last browsing session when starting the browser.", + "category": "general", + "note": null, + "default": true + }, + { + "key": "save_session_continuously", + "name": "Enable crash recovery", + "description": "Continuously save session state so tabs can be restored after crashes or unexpected closures (ALT+F4).", + "category": "general", + "note": null, + "default": true } ] diff --git a/assets/ui.css b/assets/ui.css index c9cc8b1..46f528f 100644 --- a/assets/ui.css +++ b/assets/ui.css @@ -300,4 +300,110 @@ body.compact-tabs .icon { body.compact-tabs #toggle-downloads .downloads-badge { top: 0; +} + +/* Session Restore Bar */ +#session-restore-bar { + display: none; + position: fixed; + top: 0; + left: 0; + right: 0; + background: linear-gradient(180deg, #2d4a6f 0%, #1e3a5f 100%); + border-bottom: 1px solid #3d6a9f; + padding: 8px 16px; + z-index: 9999; + align-items: center; + justify-content: space-between; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); + animation: slideDown 0.3s ease-out; +} + +@keyframes slideDown { + from { + transform: translateY(-100%); + opacity: 0; + } + to { + transform: translateY(0); + opacity: 1; + } +} + +#session-restore-bar.visible { + display: flex; +} + +#session-restore-bar .restore-message { + display: flex; + align-items: center; + gap: 10px; + color: #e0e8f0; + font-size: 13px; +} + +#session-restore-bar .restore-icon { + width: 20px; + height: 20px; + fill: #7cb3e0; +} + +#session-restore-bar .restore-actions { + display: flex; + gap: 8px; +} + +#session-restore-bar .restore-btn { + padding: 6px 14px; + border-radius: 4px; + border: none; + font-size: 12px; + font-weight: 500; + cursor: pointer; + transition: background-color 0.2s, transform 0.1s; +} + +#session-restore-bar .restore-btn:hover { + transform: translateY(-1px); +} + +#session-restore-bar .restore-btn:active { + transform: translateY(0); +} + +#session-restore-bar .restore-btn.primary { + background: #4a9eff; + color: white; +} + +#session-restore-bar .restore-btn.primary:hover { + background: #5aadff; +} + +#session-restore-bar .restore-btn.secondary { + background: rgba(255, 255, 255, 0.1); + color: #c0d0e0; + border: 1px solid rgba(255, 255, 255, 0.2); +} + +#session-restore-bar .restore-btn.secondary:hover { + background: rgba(255, 255, 255, 0.15); +} + +#session-restore-bar .dismiss-btn { + background: none; + border: none; + color: #8090a0; + cursor: pointer; + padding: 4px; + margin-left: 8px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; +} + +#session-restore-bar .dismiss-btn:hover { + background: rgba(255, 255, 255, 0.1); + color: #c0d0e0; } \ No newline at end of file diff --git a/assets/ui.html b/assets/ui.html index 34bd438..7f0e2a4 100644 --- a/assets/ui.html +++ b/assets/ui.html @@ -94,7 +94,26 @@ - + + +