URL UI, history UI
39
README.md
@@ -19,51 +19,16 @@ TODO:
|
|||||||
10. < input type=**datetime** />, essentially a type "date" but with a vertical separator, then `mm | ss | FORMAT` layout for time.
|
10. < input type=**datetime** />, essentially a type "date" but with a vertical separator, then `mm | ss | FORMAT` layout for time.
|
||||||
11. **< table >** component. [🔗 Related Godot proposal](https://github.com/godotengine/godot-proposals/issues/97)
|
11. **< table >** component. [🔗 Related Godot proposal](https://github.com/godotengine/godot-proposals/issues/97)
|
||||||
12. **< canvas >** component should be theoretically impossible by exposing Godot `_draw()` APIs to Lua.
|
12. **< canvas >** component should be theoretically impossible by exposing Godot `_draw()` APIs to Lua.
|
||||||
|
13. `grid` display property for CSS, using `GridContainer` in Godot.
|
||||||
|
|
||||||
Issues:
|
Issues:
|
||||||
1. **< br />** counts as 1 element in **WebsiteContainer**, therefore despite being (0,0) in size, it counts as double in spacing
|
1. **< br />** counts as 1 element in **WebsiteContainer**, therefore despite being (0,0) in size, it counts as double in spacing
|
||||||
2. **Tween** API doesn't modify CSS, it operates independently at Godot level.
|
2. **Tween** API doesn't modify CSS, it operates independently at Godot level.
|
||||||
3. Certain properties like `scale` and `rotate` don't apply to the `active` pseudo-class because they rely on mouse_enter and mouse_exit events
|
3. Certain properties like `scale` and `rotate` don't apply to the `active` pseudo-class because they rely on mouse_enter and mouse_exit events
|
||||||
4. `<div style="bg-[#3b82f6] w-[100px] h-[100px] flex hover:scale-110 transition hover:rotate-45">Box</div>` something like this has the "Box" text (presumably the PanelContainer) as the target of the hover, not the div itself (which has the w/h size)
|
4. `<div style="bg-[#3b82f6] w-[100px] h-[100px] flex hover:scale-110 transition hover:rotate-45">Box</div>` something like this has the "Box" text (presumably the PanelContainer) as the target of the hover, not the div itself (which has the w/h size)
|
||||||
|
5. font in button doesn't comply with CSS, its the projects default
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
- **< input />** is sort-of inline in normal web. We render it as a block element (new-line).
|
- **< input />** is sort-of inline in normal web. We render it as a block element (new-line).
|
||||||
- A single `RichTextLabel` for inline text tags should stop, we should use invididual ones so it's easier to style and achieve separation through a `vboxcontainer`.
|
- A single `RichTextLabel` for inline text tags should stop, we should use invididual ones so it's easier to style and achieve separation through a `vboxcontainer`.
|
||||||
- Fonts use **Flash of Unstyled Text (FOUT)** as opposed to **Flash of Invisible Text (FOIT)**, meaning the text with custom fonts will render with a generic font (sans-serif) while the custom ones downloads.
|
- Fonts use **Flash of Unstyled Text (FOUT)** as opposed to **Flash of Invisible Text (FOIT)**, meaning the text with custom fonts will render with a generic font (sans-serif) while the custom ones downloads.
|
||||||
|
|
||||||
Supported styles:
|
|
||||||
|
|
||||||
- **Font style:**
|
|
||||||
- `font-bold`
|
|
||||||
- `font-italic`
|
|
||||||
- `underline`
|
|
||||||
- **Font size:**
|
|
||||||
- `text-xs` → 12
|
|
||||||
- `text-sm` → 14
|
|
||||||
- `text-base` → 16
|
|
||||||
- `text-lg` → 18
|
|
||||||
- `text-xl` → 20
|
|
||||||
- `text-2xl` → 24
|
|
||||||
- `text-3xl` → 30
|
|
||||||
- `text-4xl` → 36
|
|
||||||
- `text-5xl` → 48
|
|
||||||
- `text-6xl` → 60
|
|
||||||
- **Font family:**
|
|
||||||
- `font-mono`
|
|
||||||
- **Text color:**
|
|
||||||
- `text-[color]`
|
|
||||||
- **Background color:**
|
|
||||||
- `bg-[color]`
|
|
||||||
- **Flexbox**
|
|
||||||
- `flex` / `inline-flex` (display: flex/inline-flex)
|
|
||||||
- `flex-row`, `flex-row-reverse`, `flex-col`, `flex-col-reverse` (flex-direction)
|
|
||||||
- `flex-nowrap`, `flex-wrap`, `flex-wrap-reverse` (flex-wrap)
|
|
||||||
- `justify-start`, `justify-end`, `justify-center`, `justify-between`, `justify-around`, `justify-evenly` (justify-content)
|
|
||||||
- `items-start`, `items-end`, `items-center`, `items-baseline`, `items-stretch` (align-items)
|
|
||||||
- `content-start`, `content-end`, `content-center`, `content-between`, `content-around`, `content-evenly`, `content-stretch` (align-content)
|
|
||||||
- `gap-{size}`, `row-gap-{size}`, `col-gap-{size}` (gap, row-gap, column-gap)
|
|
||||||
- `flex-grow-{n}` (flex-grow)
|
|
||||||
- `flex-shrink-{n}` (flex-shrink)
|
|
||||||
- `basis-{size}` (flex-basis)
|
|
||||||
- `self-auto`, `self-start`, `self-end`, `self-center`, `self-stretch`, `self-baseline` (align-self)
|
|
||||||
- `order-{n}` (order)
|
|
||||||
|
|||||||
1
flumi/Assets/Icons/checkbox_white.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 134 134" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;"><path d="M129.026,35.376l0,62.54c0,17.225 -13.984,31.208 -31.208,31.208l-62.416,0c-17.224,0 -31.208,-13.983 -31.208,-31.208l-0,-62.54c-0,-17.224 13.984,-31.208 31.208,-31.208l62.416,0c17.224,0 31.208,13.984 31.208,31.208Z" style="fill:none;stroke:#fff;stroke-width:8.33px;"/></svg>
|
||||||
|
After Width: | Height: | Size: 746 B |
37
flumi/Assets/Icons/checkbox_white.svg.import
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://blskvfjswul1d"
|
||||||
|
path="res://.godot/imported/checkbox_white.svg-3c05c756132e06b6df4f4ae643f84518.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Icons/checkbox_white.svg"
|
||||||
|
dest_files=["res://.godot/imported/checkbox_white.svg-3c05c756132e06b6df4f4ae643f84518.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
||||||
1
flumi/Assets/Icons/download.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
|
||||||
|
After Width: | Height: | Size: 332 B |
37
flumi/Assets/Icons/download.svg.import
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cbwitcygwoqdo"
|
||||||
|
path="res://.godot/imported/download.svg-a21cd5d191a2f0c8e42168f24a4d40ed.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Icons/download.svg"
|
||||||
|
dest_files=["res://.godot/imported/download.svg-a21cd5d191a2f0c8e42168f24a4d40ed.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
||||||
1
flumi/Assets/Icons/ellipsis-vertical.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-ellipsis-vertical-icon lucide-ellipsis-vertical"><circle cx="12" cy="12" r="1"/><circle cx="12" cy="5" r="1"/><circle cx="12" cy="19" r="1"/></svg>
|
||||||
|
After Width: | Height: | Size: 344 B |
37
flumi/Assets/Icons/ellipsis-vertical.svg.import
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cklatjc4m38dy"
|
||||||
|
path="res://.godot/imported/ellipsis-vertical.svg-294910634c008df812f7ef47e8a8a214.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Icons/ellipsis-vertical.svg"
|
||||||
|
dest_files=["res://.godot/imported/ellipsis-vertical.svg-294910634c008df812f7ef47e8a8a214.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
||||||
1
flumi/Assets/Icons/external-link.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-external-link-icon lucide-external-link"><path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/></svg>
|
||||||
|
After Width: | Height: | Size: 356 B |
37
flumi/Assets/Icons/external-link.svg.import
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://du24f6em2nqwq"
|
||||||
|
path="res://.godot/imported/external-link.svg-075235ddf5518da7b64a7c5332224a40.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Icons/external-link.svg"
|
||||||
|
dest_files=["res://.godot/imported/external-link.svg-075235ddf5518da7b64a7c5332224a40.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
||||||
1
flumi/Assets/Icons/hat-glasses.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-hat-glasses-icon lucide-hat-glasses"><path d="M14 18a2 2 0 0 0-4 0"/><path d="m19 11-2.11-6.657a2 2 0 0 0-2.752-1.148l-1.276.61A2 2 0 0 1 12 4H8.5a2 2 0 0 0-1.925 1.456L5 11"/><path d="M2 11h20"/><circle cx="17" cy="18" r="3"/><circle cx="7" cy="18" r="3"/></svg>
|
||||||
|
After Width: | Height: | Size: 460 B |
37
flumi/Assets/Icons/hat-glasses.svg.import
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dwxquqmmd6dqx"
|
||||||
|
path="res://.godot/imported/hat-glasses.svg-a7dbfb316472ae1702496a78a0ce47e7.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Icons/hat-glasses.svg"
|
||||||
|
dest_files=["res://.godot/imported/hat-glasses.svg-a7dbfb316472ae1702496a78a0ce47e7.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
||||||
1
flumi/Assets/Icons/history.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-history-icon lucide-history"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/><path d="M12 7v5l4 2"/></svg>
|
||||||
|
After Width: | Height: | Size: 336 B |
37
flumi/Assets/Icons/history.svg.import
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bcaoarwrwqbby"
|
||||||
|
path="res://.godot/imported/history.svg-ce846a8aaa80f3d2f2a595f430c7ab7c.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Icons/history.svg"
|
||||||
|
dest_files=["res://.godot/imported/history.svg-ce846a8aaa80f3d2f2a595f430c7ab7c.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
||||||
1
flumi/Assets/Icons/log-out.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-log-out-icon lucide-log-out"><path d="m16 17 5-5-5-5"/><path d="M21 12H9"/><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/></svg>
|
||||||
|
After Width: | Height: | Size: 329 B |
37
flumi/Assets/Icons/log-out.svg.import
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cilwaxcv5dr1i"
|
||||||
|
path="res://.godot/imported/log-out.svg-85530e4e6b0167a15c809830d3302ef2.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Icons/log-out.svg"
|
||||||
|
dest_files=["res://.godot/imported/log-out.svg-85530e4e6b0167a15c809830d3302ef2.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
||||||
1
flumi/Assets/Icons/message-circle-question-mark.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-message-circle-question-mark-icon lucide-message-circle-question-mark"><path d="M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/></svg>
|
||||||
|
After Width: | Height: | Size: 479 B |
37
flumi/Assets/Icons/message-circle-question-mark.svg.import
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://c5pr3tb8rwxb8"
|
||||||
|
path="res://.godot/imported/message-circle-question-mark.svg-6e0198922e95be66aacb1420c83ea704.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Icons/message-circle-question-mark.svg"
|
||||||
|
dest_files=["res://.godot/imported/message-circle-question-mark.svg-6e0198922e95be66aacb1420c83ea704.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
||||||
1
flumi/Assets/Icons/settings.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-settings-icon lucide-settings"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915"/><circle cx="12" cy="12" r="3"/></svg>
|
||||||
|
After Width: | Height: | Size: 604 B |
37
flumi/Assets/Icons/settings.svg.import
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://mjr3nwamrqon"
|
||||||
|
path="res://.godot/imported/settings.svg-2aa0f389da6ad0a7e346738ae84fd469.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Icons/settings.svg"
|
||||||
|
dest_files=["res://.godot/imported/settings.svg-2aa0f389da6ad0a7e346738ae84fd469.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
||||||
1
flumi/Assets/Icons/square.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-square-icon lucide-square"><rect width="18" height="18" x="3" y="3" rx="2"/></svg>
|
||||||
|
After Width: | Height: | Size: 279 B |
37
flumi/Assets/Icons/square.svg.import
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://81l2fi381yub"
|
||||||
|
path="res://.godot/imported/square.svg-64faf57e7837716ed0ed796cd3df54d8.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Icons/square.svg"
|
||||||
|
dest_files=["res://.godot/imported/square.svg-64faf57e7837716ed0ed796cd3df54d8.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
||||||
1
flumi/Assets/Icons/star.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-star-icon lucide-star"><path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z"/></svg>
|
||||||
|
After Width: | Height: | Size: 602 B |
37
flumi/Assets/Icons/star.svg.import
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://codete2cbsqo2"
|
||||||
|
path="res://.godot/imported/star.svg-680978d494bec0663c353c2873105a07.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Icons/star.svg"
|
||||||
|
dest_files=["res://.godot/imported/star.svg-680978d494bec0663c353c2873105a07.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
||||||
BIN
flumi/Assets/Inter-VariableFont_opsz,wght.ttf
Normal file
35
flumi/Assets/Inter-VariableFont_opsz,wght.ttf.import
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="font_data_dynamic"
|
||||||
|
type="FontFile"
|
||||||
|
uid="uid://fij84uxfqh4h"
|
||||||
|
path="res://.godot/imported/Inter-VariableFont_opsz,wght.ttf-c02350de2ed9338f034e978775e464ff.fontdata"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Inter-VariableFont_opsz,wght.ttf"
|
||||||
|
dest_files=["res://.godot/imported/Inter-VariableFont_opsz,wght.ttf-c02350de2ed9338f034e978775e464ff.fontdata"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
Rendering=null
|
||||||
|
antialiasing=1
|
||||||
|
generate_mipmaps=false
|
||||||
|
disable_embedded_bitmaps=true
|
||||||
|
multichannel_signed_distance_field=false
|
||||||
|
msdf_pixel_range=8
|
||||||
|
msdf_size=48
|
||||||
|
allow_system_fallback=true
|
||||||
|
force_autohinter=false
|
||||||
|
hinting=1
|
||||||
|
subpixel_positioning=4
|
||||||
|
keep_rounding_remainders=true
|
||||||
|
oversampling=0.0
|
||||||
|
Fallbacks=null
|
||||||
|
fallbacks=[]
|
||||||
|
Compress=null
|
||||||
|
compress=true
|
||||||
|
preload=[]
|
||||||
|
language_support={}
|
||||||
|
script_support={}
|
||||||
|
opentype_features={}
|
||||||
326
flumi/Scenes/BrowserMenus/history.tscn
Normal file
@@ -0,0 +1,326 @@
|
|||||||
|
[gd_scene load_steps=15 format=3 uid="uid://cn24pafwdpb1q"]
|
||||||
|
|
||||||
|
[ext_resource type="Texture2D" uid="uid://ctpe0lbehepen" path="res://Assets/gurted.svg" id="1_occ3h"]
|
||||||
|
[ext_resource type="Script" uid="uid://ektopbvnhfga" path="res://Scripts/history.gd" id="1_yn8i4"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://3smiker6ni50" path="res://Scenes/BrowserMenus/history_entry.tscn" id="2_a5287"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://gq8g7t4s3ryg" path="res://Assets/Icons/x.svg" id="2_ijpe2"]
|
||||||
|
[ext_resource type="Theme" uid="uid://bn6rbmdy60lhr" path="res://Scenes/Styles/BrowserText.tres" id="3_yoadi"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ijpe2"]
|
||||||
|
content_margin_left = 15.0
|
||||||
|
content_margin_top = 5.0
|
||||||
|
content_margin_right = 15.0
|
||||||
|
content_margin_bottom = 5.0
|
||||||
|
bg_color = Color(0.105882, 0.105882, 0.105882, 1)
|
||||||
|
corner_radius_top_left = 15
|
||||||
|
corner_radius_top_right = 15
|
||||||
|
corner_radius_bottom_right = 15
|
||||||
|
corner_radius_bottom_left = 15
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_yn8i4"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_a8gu8"]
|
||||||
|
bg_color = Color(0.169245, 0.169245, 0.169245, 1)
|
||||||
|
border_width_left = 2
|
||||||
|
border_width_top = 2
|
||||||
|
border_width_right = 2
|
||||||
|
border_width_bottom = 2
|
||||||
|
border_color = Color(0.247059, 0.466667, 0.807843, 1)
|
||||||
|
corner_radius_top_left = 25
|
||||||
|
corner_radius_top_right = 25
|
||||||
|
corner_radius_bottom_right = 25
|
||||||
|
corner_radius_bottom_left = 25
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_31fx5"]
|
||||||
|
draw_center = false
|
||||||
|
border_width_left = 2
|
||||||
|
border_width_top = 2
|
||||||
|
border_width_right = 2
|
||||||
|
border_width_bottom = 2
|
||||||
|
border_color = Color(0.247059, 0.466667, 0.807843, 1)
|
||||||
|
corner_radius_top_left = 25
|
||||||
|
corner_radius_top_right = 25
|
||||||
|
corner_radius_bottom_right = 25
|
||||||
|
corner_radius_bottom_left = 25
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_8gbba"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_8gbba"]
|
||||||
|
bg_color = Color(0.168627, 0.168627, 0.168627, 1)
|
||||||
|
corner_radius_top_left = 15
|
||||||
|
corner_radius_top_right = 15
|
||||||
|
corner_radius_bottom_right = 15
|
||||||
|
corner_radius_bottom_left = 15
|
||||||
|
expand_margin_left = 40.0
|
||||||
|
|
||||||
|
[sub_resource type="Theme" id="Theme_ijpe2"]
|
||||||
|
LineEdit/styles/focus = SubResource("StyleBoxEmpty_8gbba")
|
||||||
|
LineEdit/styles/normal = SubResource("StyleBoxFlat_8gbba")
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_a5287"]
|
||||||
|
content_margin_left = 10.0
|
||||||
|
bg_color = Color(0.219501, 0.219501, 0.219501, 1)
|
||||||
|
corner_radius_top_left = 15
|
||||||
|
corner_radius_top_right = 15
|
||||||
|
corner_radius_bottom_right = 15
|
||||||
|
corner_radius_bottom_left = 15
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_yn8i4"]
|
||||||
|
content_margin_left = 15.0
|
||||||
|
content_margin_top = 15.0
|
||||||
|
content_margin_right = 15.0
|
||||||
|
content_margin_bottom = 5.0
|
||||||
|
bg_color = Color(0.105882, 0.105882, 0.105882, 1)
|
||||||
|
corner_radius_top_left = 15
|
||||||
|
corner_radius_top_right = 15
|
||||||
|
corner_radius_bottom_right = 15
|
||||||
|
corner_radius_bottom_left = 15
|
||||||
|
|
||||||
|
[node name="History" type="MarginContainer"]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_constants/margin_left = 20
|
||||||
|
theme_override_constants/margin_top = 20
|
||||||
|
theme_override_constants/margin_right = 20
|
||||||
|
script = ExtResource("1_yn8i4")
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="."]
|
||||||
|
custom_minimum_size = Vector2(400, 100)
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="TextureRect" type="TextureRect" parent="Control"]
|
||||||
|
layout_mode = 1
|
||||||
|
offset_right = 417.0
|
||||||
|
offset_bottom = 417.0
|
||||||
|
scale = Vector2(0.105, 0.105)
|
||||||
|
texture = ExtResource("1_occ3h")
|
||||||
|
stretch_mode = 2
|
||||||
|
|
||||||
|
[node name="RichTextLabel" type="RichTextLabel" parent="Control"]
|
||||||
|
layout_mode = 0
|
||||||
|
offset_left = 50.0
|
||||||
|
offset_top = 9.0
|
||||||
|
offset_right = 339.0
|
||||||
|
offset_bottom = 85.0
|
||||||
|
theme_override_font_sizes/bold_font_size = 26
|
||||||
|
bbcode_enabled = true
|
||||||
|
text = "[b]History[/b]"
|
||||||
|
|
||||||
|
[node name="Main" type="VBoxContainer" parent="."]
|
||||||
|
custom_minimum_size = Vector2(600, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 4
|
||||||
|
theme_override_constants/separation = 15
|
||||||
|
|
||||||
|
[node name="DeleteMenu" type="PanelContainer" parent="Main"]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_ijpe2")
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="Main/DeleteMenu"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="CancelButton" type="Button" parent="Main/DeleteMenu/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
mouse_default_cursor_shape = 2
|
||||||
|
theme_override_styles/focus = SubResource("StyleBoxEmpty_yn8i4")
|
||||||
|
icon = ExtResource("2_ijpe2")
|
||||||
|
flat = true
|
||||||
|
icon_alignment = 1
|
||||||
|
|
||||||
|
[node name="RichTextLabel" type="RichTextLabel" parent="Main/DeleteMenu/HBoxContainer"]
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "1 selected"
|
||||||
|
fit_content = true
|
||||||
|
vertical_alignment = 1
|
||||||
|
|
||||||
|
[node name="DeleteButton" type="Button" parent="Main/DeleteMenu/HBoxContainer"]
|
||||||
|
custom_minimum_size = Vector2(80, 35)
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 10
|
||||||
|
mouse_default_cursor_shape = 2
|
||||||
|
theme = ExtResource("3_yoadi")
|
||||||
|
theme_override_colors/font_color = Color(0.781065, 0.858202, 0.977018, 1)
|
||||||
|
theme_override_styles/hover = SubResource("StyleBoxFlat_a8gu8")
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxFlat_31fx5")
|
||||||
|
text = "Delete"
|
||||||
|
|
||||||
|
[node name="LineEdit" type="LineEdit" parent="Main"]
|
||||||
|
custom_minimum_size = Vector2(0, 45)
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
theme = SubResource("Theme_ijpe2")
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxFlat_a5287")
|
||||||
|
placeholder_text = "Search history..."
|
||||||
|
caret_blink = true
|
||||||
|
|
||||||
|
[node name="HSeparator" type="HSeparator" parent="Main"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="PanelContainer2" type="PanelContainer" parent="Main"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_yn8i4")
|
||||||
|
|
||||||
|
[node name="ScrollContainer" type="ScrollContainer" parent="Main/PanelContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="HistoryEntryContainer" type="VBoxContainer" parent="Main/PanelContainer2/ScrollContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
alignment = 1
|
||||||
|
|
||||||
|
[node name="HistoryEntry" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry2" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry3" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry4" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry5" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry6" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry7" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry8" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry9" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry10" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry11" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry12" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry13" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry14" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry15" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry16" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry17" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry18" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry19" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry20" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry21" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry22" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry23" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry24" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry25" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry26" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry27" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry28" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry29" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry30" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry31" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry32" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry33" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry34" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry35" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry36" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry37" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry38" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry39" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry40" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry41" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry42" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry43" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry44" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry45" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry46" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry47" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry48" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HistoryEntry49" parent="Main/PanelContainer2/ScrollContainer/HistoryEntryContainer" instance=ExtResource("2_a5287")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[connection signal="pressed" from="Main/DeleteMenu/HBoxContainer/CancelButton" to="." method="_on_cancel_button_pressed"]
|
||||||
42
flumi/Scenes/BrowserMenus/history_entry.tscn
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
[gd_scene load_steps=5 format=3 uid="uid://3smiker6ni50"]
|
||||||
|
|
||||||
|
[ext_resource type="Theme" uid="uid://bn6rbmdy60lhr" path="res://Scenes/Styles/BrowserText.tres" id="1_4plhl"]
|
||||||
|
[ext_resource type="Script" uid="uid://bw5pr4wrf780h" path="res://Scripts/history_entry.gd" id="1_h5c6k"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://blskvfjswul1d" path="res://Assets/Icons/checkbox_white.svg" id="2_h5c6k"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://bqpx2lgo0yecb" path="res://Assets/Icons/globe.svg" id="2_k4hqm"]
|
||||||
|
|
||||||
|
[node name="HistoryEntry" type="HBoxContainer"]
|
||||||
|
theme_override_constants/separation = 10
|
||||||
|
script = ExtResource("1_h5c6k")
|
||||||
|
|
||||||
|
[node name="CheckBox" type="CheckBox" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
theme = ExtResource("1_4plhl")
|
||||||
|
theme_override_icons/unchecked = ExtResource("2_h5c6k")
|
||||||
|
flat = true
|
||||||
|
|
||||||
|
[node name="RichTextLabel" type="RichTextLabel" parent="."]
|
||||||
|
custom_minimum_size = Vector2(60, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "2:00PM"
|
||||||
|
fit_content = true
|
||||||
|
horizontal_alignment = 1
|
||||||
|
vertical_alignment = 1
|
||||||
|
|
||||||
|
[node name="Spacer" type="Control" parent="."]
|
||||||
|
custom_minimum_size = Vector2(50, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="TextureRect" type="TextureRect" parent="."]
|
||||||
|
custom_minimum_size = Vector2(24, 24)
|
||||||
|
layout_mode = 2
|
||||||
|
texture = ExtResource("2_k4hqm")
|
||||||
|
stretch_mode = 3
|
||||||
|
|
||||||
|
[node name="RichTextLabel2" type="RichTextLabel" parent="."]
|
||||||
|
custom_minimum_size = Vector2(350, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Selection - Google Fonts"
|
||||||
|
vertical_alignment = 1
|
||||||
|
|
||||||
|
[connection signal="toggled" from="CheckBox" to="." method="_on_check_box_toggled"]
|
||||||
@@ -112,10 +112,10 @@ content_margin_top = 15.0
|
|||||||
content_margin_right = 15.0
|
content_margin_right = 15.0
|
||||||
content_margin_bottom = 15.0
|
content_margin_bottom = 15.0
|
||||||
bg_color = Color(0.168627, 0.168627, 0.168627, 1)
|
bg_color = Color(0.168627, 0.168627, 0.168627, 1)
|
||||||
corner_radius_top_left = 15
|
corner_radius_top_left = 10
|
||||||
corner_radius_top_right = 15
|
corner_radius_top_right = 10
|
||||||
corner_radius_bottom_right = 15
|
corner_radius_bottom_right = 10
|
||||||
corner_radius_bottom_left = 15
|
corner_radius_bottom_left = 10
|
||||||
|
|
||||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ya683"]
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ya683"]
|
||||||
content_margin_left = 15.0
|
content_margin_left = 15.0
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ anchors_preset = 10
|
|||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
offset_bottom = 19.0
|
offset_bottom = 19.0
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
focus_mode = 2
|
focus_mode = 2
|
||||||
mouse_default_cursor_shape = 1
|
mouse_default_cursor_shape = 1
|
||||||
theme = ExtResource("2_1glvj")
|
theme = ExtResource("2_1glvj")
|
||||||
@@ -15,5 +16,6 @@ theme_override_colors/default_color = Color(0, 0, 0, 1)
|
|||||||
bbcode_enabled = true
|
bbcode_enabled = true
|
||||||
text = "Placeholder"
|
text = "Placeholder"
|
||||||
fit_content = true
|
fit_content = true
|
||||||
|
vertical_alignment = 1
|
||||||
selection_enabled = true
|
selection_enabled = true
|
||||||
script = ExtResource("1_pnbfg")
|
script = ExtResource("1_pnbfg")
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[gd_scene load_steps=27 format=3 uid="uid://bytm7bt2s4ak8"]
|
[gd_scene load_steps=40 format=3 uid="uid://bytm7bt2s4ak8"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://bg5iqnwic1rio" path="res://Scripts/main.gd" id="1_8q3xr"]
|
[ext_resource type="Script" uid="uid://bg5iqnwic1rio" path="res://Scripts/main.gd" id="1_8q3xr"]
|
||||||
[ext_resource type="Texture2D" uid="uid://df1m4j7uxi63v" path="res://Assets/Icons/chevron-down.svg" id="2_6bp64"]
|
[ext_resource type="Texture2D" uid="uid://df1m4j7uxi63v" path="res://Assets/Icons/chevron-down.svg" id="2_6bp64"]
|
||||||
@@ -9,8 +9,21 @@
|
|||||||
[ext_resource type="PackedScene" uid="uid://sqhcxhcre081" path="res://Scenes/Tab.tscn" id="4_344ge"]
|
[ext_resource type="PackedScene" uid="uid://sqhcxhcre081" path="res://Scenes/Tab.tscn" id="4_344ge"]
|
||||||
[ext_resource type="Texture2D" uid="uid://cu4hjoba6etf" path="res://Assets/Icons/rotate-cw.svg" id="5_344ge"]
|
[ext_resource type="Texture2D" uid="uid://cu4hjoba6etf" path="res://Assets/Icons/rotate-cw.svg" id="5_344ge"]
|
||||||
[ext_resource type="Texture2D" uid="uid://cehbtwq6gq0cn" path="res://Assets/Icons/plus.svg" id="5_ynf5e"]
|
[ext_resource type="Texture2D" uid="uid://cehbtwq6gq0cn" path="res://Assets/Icons/plus.svg" id="5_ynf5e"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://cklatjc4m38dy" path="res://Assets/Icons/ellipsis-vertical.svg" id="10_6iyac"]
|
||||||
[ext_resource type="Script" uid="uid://bgqglerkcylxx" path="res://addons/SmoothScroll/SmoothScrollContainer.gd" id="10_d1ilt"]
|
[ext_resource type="Script" uid="uid://bgqglerkcylxx" path="res://addons/SmoothScroll/SmoothScrollContainer.gd" id="10_d1ilt"]
|
||||||
[ext_resource type="Script" uid="uid://b7h0k2h2qwlqv" path="res://addons/SmoothScroll/scroll_damper/expo_scroll_damper.gd" id="11_6iyac"]
|
[ext_resource type="Script" uid="uid://b7h0k2h2qwlqv" path="res://addons/SmoothScroll/scroll_damper/expo_scroll_damper.gd" id="11_6iyac"]
|
||||||
|
[ext_resource type="Theme" uid="uid://bn6rbmdy60lhr" path="res://Scenes/Styles/BrowserText.tres" id="11_ee4r6"]
|
||||||
|
[ext_resource type="Script" uid="uid://vjjhljlftlbk" path="res://Scripts/OptionButton.gd" id="11_gt3je"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://du24f6em2nqwq" path="res://Assets/Icons/external-link.svg" id="12_gt3je"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://81l2fi381yub" path="res://Assets/Icons/square.svg" id="13_3pmx8"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dwxquqmmd6dqx" path="res://Assets/Icons/hat-glasses.svg" id="14_u50mg"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://bcaoarwrwqbby" path="res://Assets/Icons/history.svg" id="15_cbgmd"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://cbwitcygwoqdo" path="res://Assets/Icons/download.svg" id="16_1w6v2"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://codete2cbsqo2" path="res://Assets/Icons/star.svg" id="17_ueoa1"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://c5pr3tb8rwxb8" path="res://Assets/Icons/message-circle-question-mark.svg" id="18_6vcvc"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://mjr3nwamrqon" path="res://Assets/Icons/settings.svg" id="19_7k868"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://cilwaxcv5dr1i" path="res://Assets/Icons/log-out.svg" id="20_hpc6h"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://cn24pafwdpb1q" path="res://Scenes/BrowserMenus/history.tscn" id="24_3pmx8"]
|
||||||
|
|
||||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_344ge"]
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_344ge"]
|
||||||
|
|
||||||
@@ -49,9 +62,9 @@ corner_radius_bottom_left = 50
|
|||||||
bg_color = Color(0.6, 0.6, 0.6, 0)
|
bg_color = Color(0.6, 0.6, 0.6, 0)
|
||||||
draw_center = false
|
draw_center = false
|
||||||
|
|
||||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_8gbba"]
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_u50mg"]
|
||||||
|
|
||||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_8gbba"]
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_cbgmd"]
|
||||||
bg_color = Color(0.168627, 0.168627, 0.168627, 1)
|
bg_color = Color(0.168627, 0.168627, 0.168627, 1)
|
||||||
corner_radius_top_left = 15
|
corner_radius_top_left = 15
|
||||||
corner_radius_top_right = 15
|
corner_radius_top_right = 15
|
||||||
@@ -60,8 +73,8 @@ corner_radius_bottom_left = 15
|
|||||||
expand_margin_left = 40.0
|
expand_margin_left = 40.0
|
||||||
|
|
||||||
[sub_resource type="Theme" id="Theme_jjvhh"]
|
[sub_resource type="Theme" id="Theme_jjvhh"]
|
||||||
LineEdit/styles/focus = SubResource("StyleBoxEmpty_8gbba")
|
LineEdit/styles/focus = SubResource("StyleBoxEmpty_u50mg")
|
||||||
LineEdit/styles/normal = SubResource("StyleBoxFlat_8gbba")
|
LineEdit/styles/normal = SubResource("StyleBoxFlat_cbgmd")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_fdnlq"]
|
[sub_resource type="Resource" id="Resource_fdnlq"]
|
||||||
script = ExtResource("11_6iyac")
|
script = ExtResource("11_6iyac")
|
||||||
@@ -200,6 +213,59 @@ scale = Vector2(0.85, 0.85)
|
|||||||
texture = ExtResource("3_8gbba")
|
texture = ExtResource("3_8gbba")
|
||||||
stretch_mode = 5
|
stretch_mode = 5
|
||||||
|
|
||||||
|
[node name="OptionsButton" type="Button" parent="VBoxContainer/HBoxContainer"]
|
||||||
|
custom_minimum_size = Vector2(45, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/focus = SubResource("StyleBoxEmpty_d1ilt")
|
||||||
|
theme_override_styles/hover = SubResource("StyleBoxFlat_fdnlq")
|
||||||
|
theme_override_styles/pressed = SubResource("StyleBoxFlat_d1ilt")
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxFlat_d1ilt")
|
||||||
|
icon = ExtResource("10_6iyac")
|
||||||
|
icon_alignment = 1
|
||||||
|
script = ExtResource("11_gt3je")
|
||||||
|
|
||||||
|
[node name="OptionsMenu" type="PopupMenu" parent="VBoxContainer/HBoxContainer/OptionsButton"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
position = Vector2i(1510, 125)
|
||||||
|
size = Vector2i(408, 360)
|
||||||
|
theme = ExtResource("11_ee4r6")
|
||||||
|
theme_override_constants/v_separation = 10
|
||||||
|
item_count = 11
|
||||||
|
item_0/text = "New tab (CTRL T)"
|
||||||
|
item_0/icon = ExtResource("12_gt3je")
|
||||||
|
item_0/id = 0
|
||||||
|
item_1/text = "New window (CTRL N)"
|
||||||
|
item_1/icon = ExtResource("13_3pmx8")
|
||||||
|
item_1/id = 1
|
||||||
|
item_2/text = "New Incognito Window (CTRL SHIFT N)"
|
||||||
|
item_2/icon = ExtResource("14_u50mg")
|
||||||
|
item_2/id = 2
|
||||||
|
item_3/id = 3
|
||||||
|
item_3/separator = true
|
||||||
|
item_4/text = "History (CTRL H)"
|
||||||
|
item_4/icon = ExtResource("15_cbgmd")
|
||||||
|
item_4/id = 4
|
||||||
|
item_5/text = "Downloads (CTRL J)"
|
||||||
|
item_5/icon = ExtResource("16_1w6v2")
|
||||||
|
item_5/id = 5
|
||||||
|
item_6/text = "Bookmarks (CTRL SHIFT B)"
|
||||||
|
item_6/icon = ExtResource("17_ueoa1")
|
||||||
|
item_6/id = 7
|
||||||
|
item_7/id = 7
|
||||||
|
item_7/separator = true
|
||||||
|
item_8/text = "Help"
|
||||||
|
item_8/icon = ExtResource("18_6vcvc")
|
||||||
|
item_8/id = 8
|
||||||
|
item_9/text = "Settings"
|
||||||
|
item_9/icon = ExtResource("19_7k868")
|
||||||
|
item_9/id = 9
|
||||||
|
item_10/text = "Exit"
|
||||||
|
item_10/icon = ExtResource("20_hpc6h")
|
||||||
|
item_10/id = 10
|
||||||
|
|
||||||
|
[node name="Control2" type="Control" parent="VBoxContainer/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
[node name="Spacer3" type="Control" parent="VBoxContainer"]
|
[node name="Spacer3" type="Control" parent="VBoxContainer"]
|
||||||
custom_minimum_size = Vector2(0, 2)
|
custom_minimum_size = Vector2(0, 2)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
@@ -216,12 +282,17 @@ metadata/_custom_type_script = "uid://bgqglerkcylxx"
|
|||||||
|
|
||||||
[node name="WebsiteContainer" type="VBoxContainer" parent="VBoxContainer/ScrollContainer"]
|
[node name="WebsiteContainer" type="VBoxContainer" parent="VBoxContainer/ScrollContainer"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(200, 200)
|
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
size_flags_vertical = 3
|
size_flags_vertical = 3
|
||||||
theme_override_constants/separation = 22
|
theme_override_constants/separation = 22
|
||||||
|
|
||||||
|
[node name="HistoryContainer" parent="VBoxContainer/ScrollContainer" instance=ExtResource("24_3pmx8")]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
[node name="WebsiteBackground" type="Panel" parent="."]
|
[node name="WebsiteBackground" type="Panel" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
z_index = -1
|
z_index = -1
|
||||||
@@ -259,3 +330,8 @@ mouse_filter = 2
|
|||||||
theme_override_styles/panel = SubResource("StyleBoxFlat_21xkr")
|
theme_override_styles/panel = SubResource("StyleBoxFlat_21xkr")
|
||||||
|
|
||||||
[connection signal="pressed" from="VBoxContainer/TabContainer/NewTabButton" to="VBoxContainer/TabContainer" method="_on_new_tab_button_pressed"]
|
[connection signal="pressed" from="VBoxContainer/TabContainer/NewTabButton" to="VBoxContainer/TabContainer" method="_on_new_tab_button_pressed"]
|
||||||
|
[connection signal="focus_entered" from="VBoxContainer/HBoxContainer/LineEdit" to="." method="_on_search_focus_entered"]
|
||||||
|
[connection signal="focus_exited" from="VBoxContainer/HBoxContainer/LineEdit" to="." method="_on_search_focus_exited"]
|
||||||
|
[connection signal="text_submitted" from="VBoxContainer/HBoxContainer/LineEdit" to="." method="_on_search_submitted"]
|
||||||
|
[connection signal="pressed" from="VBoxContainer/HBoxContainer/OptionsButton" to="VBoxContainer/HBoxContainer/OptionsButton" method="_on_pressed"]
|
||||||
|
[connection signal="id_pressed" from="VBoxContainer/HBoxContainer/OptionsButton/OptionsMenu" to="VBoxContainer/HBoxContainer/OptionsButton" method="_on_options_menu_id_pressed"]
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ func get_element_styles_with_inheritance(element: HTMLElement, event: String = "
|
|||||||
styles[property] = inline_parsed[property]
|
styles[property] = inline_parsed[property]
|
||||||
|
|
||||||
# Inherit certain properties from parent elements
|
# Inherit certain properties from parent elements
|
||||||
var inheritable_properties = ["width", "height", "font-size", "color", "font-family", "cursor"]
|
var inheritable_properties = ["width", "height", "font-size", "color", "font-family", "cursor", "font-bold", "font-italic", "underline"]
|
||||||
var parent_element = element.parent
|
var parent_element = element.parent
|
||||||
while parent_element:
|
while parent_element:
|
||||||
var parent_styles = get_element_styles_internal(parent_element, event)
|
var parent_styles = get_element_styles_internal(parent_element, event)
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ func _init():
|
|||||||
timeout_manager = LuaTimeoutManager.new()
|
timeout_manager = LuaTimeoutManager.new()
|
||||||
threaded_vm = ThreadedLuaVM.new()
|
threaded_vm = ThreadedLuaVM.new()
|
||||||
threaded_vm.script_completed.connect(_on_threaded_script_completed)
|
threaded_vm.script_completed.connect(_on_threaded_script_completed)
|
||||||
|
threaded_vm.script_error.connect(func(e): print(e))
|
||||||
threaded_vm.dom_operation_request.connect(_handle_dom_operation)
|
threaded_vm.dom_operation_request.connect(_handle_dom_operation)
|
||||||
threaded_vm.print_output.connect(_on_print_output)
|
threaded_vm.print_output.connect(_on_print_output)
|
||||||
|
|
||||||
|
|||||||
@@ -2794,4 +2794,108 @@ audio.play()
|
|||||||
|
|
||||||
# Set the active HTML content to use the audio demo
|
# Set the active HTML content to use the audio demo
|
||||||
func _ready():
|
func _ready():
|
||||||
HTML_CONTENT = HTML_CONTENT_AUDIO_TEST
|
HTML_CONTENT = """<head>
|
||||||
|
<title>Login</title>
|
||||||
|
<icon src="https://cdn-icons-png.flaticon.com/512/295/295128.png">
|
||||||
|
<meta name="theme-color" content="#1b1b1b">
|
||||||
|
<meta name="description" content="Login to your account">
|
||||||
|
|
||||||
|
<font name="roboto" src="https://fonts.gstatic.com/s/roboto/v48/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3KUBGEe.woff2" />
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body { bg-[#1b1b1b] text-[#ffffff] font-roboto flex items-center justify-center p-4 }
|
||||||
|
.login-card { bg-[#2a2a2a] rounded-lg p-8 shadow-2xl mx-0 }
|
||||||
|
h1 { text-3xl font-bold text-center mb-6 text-[#ffffff] }
|
||||||
|
input {
|
||||||
|
bg-[#3b3b3b]
|
||||||
|
border-none
|
||||||
|
rounded-md
|
||||||
|
p-3
|
||||||
|
w-full
|
||||||
|
text-[#ffffff]
|
||||||
|
placeholder:text-[#999999]
|
||||||
|
outline-none
|
||||||
|
focus:ring-2
|
||||||
|
focus:ring-[#5b5b5b]
|
||||||
|
mb-4
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
bg-[#4ade80]
|
||||||
|
text-[#1b1b1b]
|
||||||
|
font-bold
|
||||||
|
p-3
|
||||||
|
rounded-md
|
||||||
|
w-full
|
||||||
|
hover:bg-[#22c55e]
|
||||||
|
active:bg-[#15803d]
|
||||||
|
cursor-pointer
|
||||||
|
}
|
||||||
|
a { text-[#4ade80] hover:text-[#22c55e] cursor-pointer }
|
||||||
|
#log-output { text-white p-4 rounded-md mt-4 font-mono max-h-40 }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
local submitBtn = gurt.select('#submit')
|
||||||
|
local username_input = gurt.select('#username')
|
||||||
|
local password_input = gurt.select('#password')
|
||||||
|
local log_output = gurt.select('#log-output')
|
||||||
|
|
||||||
|
function addLog(message)
|
||||||
|
gurt.log(message)
|
||||||
|
log_output.text = log_output.text .. message .. '\\n'
|
||||||
|
end
|
||||||
|
|
||||||
|
submitBtn:on('submit', function(event)
|
||||||
|
local username = event.data.username
|
||||||
|
local password = event.data.password
|
||||||
|
|
||||||
|
local request_body = JSON.stringify({
|
||||||
|
username = username,
|
||||||
|
password = password
|
||||||
|
})
|
||||||
|
print(request_body)
|
||||||
|
local url = 'http://localhost:8080/auth/login'
|
||||||
|
local headers = {
|
||||||
|
['Content-Type'] = 'application/json'
|
||||||
|
}
|
||||||
|
|
||||||
|
addLog('Attempting to log in with username: ' .. username)
|
||||||
|
log_output.text = ''
|
||||||
|
|
||||||
|
local response = fetch(url, {
|
||||||
|
method = 'POST',
|
||||||
|
headers = headers,
|
||||||
|
body = request_body
|
||||||
|
})
|
||||||
|
|
||||||
|
addLog('Response Status: ' .. response.status .. ' ' .. response.statusText)
|
||||||
|
|
||||||
|
if response:ok() then
|
||||||
|
addLog('Login successful!')
|
||||||
|
local jsonData = response:json()
|
||||||
|
if jsonData then
|
||||||
|
addLog('Logged in as user: ' .. jsonData.user.username)
|
||||||
|
addLog('Token: ' .. jsonData.token:sub(1, 20) .. '...')
|
||||||
|
end
|
||||||
|
else
|
||||||
|
addLog('Request failed with status: ' .. response.status)
|
||||||
|
local error_data = response:text()
|
||||||
|
addLog('Error response: ' .. error_data)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div style="login-card">
|
||||||
|
<h1>Login</h1>
|
||||||
|
<form id="login-form">
|
||||||
|
<input id="username" type="text" placeholder="Username" required="true" />
|
||||||
|
<input id="password" type="password" placeholder="Password" required="true" />
|
||||||
|
<button type="submit" id="submit">Log In</button>
|
||||||
|
</form>
|
||||||
|
<p style="text-center mt-4 text-[#999999] text-base">Don't have an account? <a href="#">Register here</a></p>
|
||||||
|
|
||||||
|
<p id="log-output" style="min-h-24"></p>
|
||||||
|
</div>
|
||||||
|
</body>""".to_utf8_buffer()
|
||||||
|
|||||||
198
flumi/Scripts/GurtProtocol.gd
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
extends RefCounted
|
||||||
|
class_name GurtProtocol
|
||||||
|
|
||||||
|
const DNS_API_URL = "http://localhost:8080"
|
||||||
|
|
||||||
|
static func is_gurt_domain(url: String) -> bool:
|
||||||
|
if url.begins_with("gurt://"):
|
||||||
|
return true
|
||||||
|
|
||||||
|
var parts = url.split(".")
|
||||||
|
return parts.size() == 2 and not url.contains("://")
|
||||||
|
|
||||||
|
static func parse_gurt_domain(url: String) -> Dictionary:
|
||||||
|
print("Parsing URL: ", url)
|
||||||
|
|
||||||
|
var domain_part = url
|
||||||
|
|
||||||
|
if url.begins_with("gurt://"):
|
||||||
|
domain_part = url.substr(7) # Remove "gurt://"
|
||||||
|
|
||||||
|
var parts = domain_part.split(".")
|
||||||
|
if parts.size() != 2:
|
||||||
|
print("Invalid domain format: ", domain_part)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
print("Parsed domain - name: ", parts[0], ", tld: ", parts[1])
|
||||||
|
return {
|
||||||
|
"name": parts[0],
|
||||||
|
"tld": parts[1],
|
||||||
|
"display_url": domain_part
|
||||||
|
}
|
||||||
|
|
||||||
|
static func fetch_domain_info(name: String, tld: String) -> Dictionary:
|
||||||
|
print("Fetching domain info for: ", name, ".", tld)
|
||||||
|
|
||||||
|
var http_request = HTTPRequest.new()
|
||||||
|
var tree = Engine.get_main_loop()
|
||||||
|
tree.current_scene.add_child(http_request)
|
||||||
|
|
||||||
|
http_request.timeout = 5.0
|
||||||
|
|
||||||
|
var url = DNS_API_URL + "/domain/" + name + "/" + tld
|
||||||
|
print("DNS API URL: ", url)
|
||||||
|
|
||||||
|
var error = http_request.request(url)
|
||||||
|
|
||||||
|
if error != OK:
|
||||||
|
print("HTTP request failed with error: ", error)
|
||||||
|
http_request.queue_free()
|
||||||
|
return {"error": "Failed to make DNS request"}
|
||||||
|
|
||||||
|
var response = await http_request.request_completed
|
||||||
|
http_request.queue_free()
|
||||||
|
|
||||||
|
if response[1] == 0 and response[3].size() == 0:
|
||||||
|
print("DNS API request timed out")
|
||||||
|
return {"error": "DNS server is not responding"}
|
||||||
|
|
||||||
|
var http_code = response[1]
|
||||||
|
var body = response[3]
|
||||||
|
|
||||||
|
print("DNS API response code: ", http_code)
|
||||||
|
print("DNS API response body: ", body.get_string_from_utf8())
|
||||||
|
|
||||||
|
if http_code != 200:
|
||||||
|
return {"error": "Domain not found or not approved"}
|
||||||
|
|
||||||
|
var json = JSON.new()
|
||||||
|
var parse_result = json.parse(body.get_string_from_utf8())
|
||||||
|
|
||||||
|
if parse_result != OK:
|
||||||
|
print("JSON parse error: ", parse_result)
|
||||||
|
return {"error": "Invalid JSON response from DNS server"}
|
||||||
|
|
||||||
|
print("Domain info retrieved: ", json.data)
|
||||||
|
return json.data
|
||||||
|
|
||||||
|
static func fetch_index_html(ip: String) -> String:
|
||||||
|
print("Fetching index.html from IP: ", ip)
|
||||||
|
|
||||||
|
var http_request = HTTPRequest.new()
|
||||||
|
var tree = Engine.get_main_loop()
|
||||||
|
tree.current_scene.add_child(http_request)
|
||||||
|
|
||||||
|
http_request.timeout = 5.0
|
||||||
|
|
||||||
|
var url = "http://" + ip + "/index.html"
|
||||||
|
print("Fetching from URL: ", url)
|
||||||
|
|
||||||
|
var error = http_request.request(url)
|
||||||
|
|
||||||
|
if error != OK:
|
||||||
|
print("HTTP request to IP failed with error: ", error)
|
||||||
|
http_request.queue_free()
|
||||||
|
return ""
|
||||||
|
|
||||||
|
var response = await http_request.request_completed
|
||||||
|
http_request.queue_free()
|
||||||
|
|
||||||
|
if response[1] == 0 and response[3].size() == 0:
|
||||||
|
print("Index.html request timed out")
|
||||||
|
return ""
|
||||||
|
|
||||||
|
var http_code = response[1]
|
||||||
|
var body = response[3]
|
||||||
|
|
||||||
|
print("IP response code: ", http_code)
|
||||||
|
|
||||||
|
if http_code != 200:
|
||||||
|
print("Failed to fetch index.html, HTTP code: ", http_code)
|
||||||
|
return ""
|
||||||
|
|
||||||
|
var html_content = body.get_string_from_utf8()
|
||||||
|
print("Successfully fetched HTML content (", html_content.length(), " characters)")
|
||||||
|
return html_content
|
||||||
|
|
||||||
|
static func handle_gurt_domain(url: String) -> Dictionary:
|
||||||
|
print("Handling GURT domain: ", url)
|
||||||
|
|
||||||
|
var parsed = parse_gurt_domain(url)
|
||||||
|
if parsed.is_empty():
|
||||||
|
return {"error": "Invalid domain format. Use: domain.tld", "html": create_error_page("Invalid domain format. Use: domain.tld")}
|
||||||
|
|
||||||
|
var domain_info = await fetch_domain_info(parsed.name, parsed.tld)
|
||||||
|
if domain_info.has("error"):
|
||||||
|
return {"error": domain_info.error, "html": create_error_page(domain_info.error)}
|
||||||
|
|
||||||
|
var html_content = await fetch_index_html(domain_info.ip)
|
||||||
|
if html_content.is_empty():
|
||||||
|
var error_msg = "Failed to fetch index.html from " + domain_info.ip
|
||||||
|
return {"error": error_msg, "html": create_error_page(error_msg)}
|
||||||
|
|
||||||
|
return {"html": html_content, "display_url": parsed.display_url}
|
||||||
|
|
||||||
|
static func get_error_type(error_message: String) -> Dictionary:
|
||||||
|
if "DNS server is not responding" in error_message or "Domain not found" in error_message:
|
||||||
|
return {"code": "ERR_NAME_NOT_RESOLVED", "title": "This site can't be reached", "icon": "🌐"}
|
||||||
|
elif "timeout" in error_message.to_lower() or "timed out" in error_message.to_lower():
|
||||||
|
return {"code": "ERR_CONNECTION_TIMED_OUT", "title": "This site can't be reached", "icon": "⏰"}
|
||||||
|
elif "Failed to fetch" in error_message or "HTTP request failed" in error_message:
|
||||||
|
return {"code": "ERR_CONNECTION_REFUSED", "title": "This site can't be reached", "icon": "🚫"}
|
||||||
|
elif "Invalid domain format" in error_message:
|
||||||
|
return {"code": "ERR_INVALID_URL", "title": "This page isn't working", "icon": "⚠️"}
|
||||||
|
else:
|
||||||
|
return {"code": "ERR_UNKNOWN", "title": "Something went wrong", "icon": "❌"}
|
||||||
|
|
||||||
|
static func create_error_page(error_message: String) -> String:
|
||||||
|
var error_info = get_error_type(error_message)
|
||||||
|
|
||||||
|
return """<head>
|
||||||
|
<title>""" + error_info.title + """ - GURT</title>
|
||||||
|
<meta name="theme-color" content="#f8f9fa">
|
||||||
|
<style>
|
||||||
|
body { bg-[#ffffff] text-[#202124] font-sans p-0 m-0 }
|
||||||
|
.error-container { flex flex-col items-center justify-center max-w-[600px] mx-auto px-6 text-center }
|
||||||
|
.error-icon { text-6xl mb-6 opacity-60 w-32 h-32 }
|
||||||
|
.error-title { text-[#202124] text-2xl font-normal mb-4 line-height-1.3 }
|
||||||
|
.error-subtitle { text-[#5f6368] text-base mb-6 line-height-1.4 }
|
||||||
|
.error-code { bg-[#f8f9fa] text-[#5f6368] px-3 py-2 rounded-md font-mono text-sm inline-block mb-6 }
|
||||||
|
.suggestions { text-left max-w-[400px] w-[500px] }
|
||||||
|
.suggestion-title { text-[#202124] text-lg font-normal mb-3 }
|
||||||
|
.suggestion-list { text-[#5f6368] text-sm line-height-1.6 }
|
||||||
|
.suggestion-item { mb-2 pl-4 relative }
|
||||||
|
.suggestion-item:before { content-"•" absolute left-0 top-0 text-[#5f6368] }
|
||||||
|
.retry-button { bg-[#1a73e8] text-[#ffffff] px-6 py-3 rounded-md font-medium text-sm hover:bg-[#1557b0] active:bg-[#1246a0] cursor-pointer border-none mt-4 }
|
||||||
|
.details-section { mt-8 pt-6 border-t border-[#e8eaed] }
|
||||||
|
.details-toggle { text-[#1a73e8] text-sm cursor-pointer hover:underline }
|
||||||
|
.details-content { bg-[#f8f9fa] text-[#5f6368] text-xs font-mono p-4 rounded-md mt-3 text-left display-none }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
gurt.select("#reload"):on("click", function()
|
||||||
|
gurt.location.reload()
|
||||||
|
end)
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div style="error-container">
|
||||||
|
<p style="error-icon">""" + error_info.icon + """</p>
|
||||||
|
|
||||||
|
<h1 style="error-title">""" + error_info.title + """</h1>
|
||||||
|
|
||||||
|
<p style="error-subtitle">""" + error_message + """</p>
|
||||||
|
|
||||||
|
<div style="error-code">""" + error_info.code + """</div>
|
||||||
|
|
||||||
|
<div style="suggestions">
|
||||||
|
<h2 style="suggestion-title">Try:</h2>
|
||||||
|
<ul style="suggestion-list">
|
||||||
|
<li style="suggestion-item">Checking if the domain is correctly registered</li>
|
||||||
|
<li style="suggestion-item">Verifying your DNS server is running</li>
|
||||||
|
<li style="suggestion-item">Checking your internet connection</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button style="retry-button" id="reload">Reload</button>
|
||||||
|
</div>
|
||||||
|
</body>"""
|
||||||
1
flumi/Scripts/GurtProtocol.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://clhivwjs3eujk
|
||||||
18
flumi/Scripts/OptionButton.gd
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
extends Button
|
||||||
|
|
||||||
|
@onready var tab_container: TabManager = $"../../TabContainer"
|
||||||
|
@onready var website_background: Panel = %WebsiteBackground
|
||||||
|
|
||||||
|
func _on_pressed() -> void:
|
||||||
|
%OptionsMenu.show()
|
||||||
|
|
||||||
|
func _on_options_menu_id_pressed(id: int) -> void:
|
||||||
|
if id == 0: # new tab
|
||||||
|
tab_container.create_tab()
|
||||||
|
if id == 1: # new window
|
||||||
|
OS.create_process(OS.get_executable_path(), [])
|
||||||
|
if id == 2: # new ingonito window
|
||||||
|
# TODO: handle incognito
|
||||||
|
OS.create_process(OS.get_executable_path(), ["--incognito"])
|
||||||
|
if id == 4: # history
|
||||||
|
website_background.modulate = Constants.SECONDARY_COLOR
|
||||||
1
flumi/Scripts/OptionButton.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://vjjhljlftlbk
|
||||||
@@ -318,16 +318,23 @@ static func apply_margin_wrapper(node: Control, styles: Dictionary) -> Control:
|
|||||||
var margin_container = MarginContainer.new()
|
var margin_container = MarginContainer.new()
|
||||||
margin_container.name = "MarginWrapper_" + node.name
|
margin_container.name = "MarginWrapper_" + node.name
|
||||||
|
|
||||||
# Copy size flags from the original node
|
var has_explicit_width = styles.has("width")
|
||||||
margin_container.size_flags_horizontal = node.size_flags_horizontal
|
var has_explicit_height = styles.has("height")
|
||||||
margin_container.size_flags_vertical = node.size_flags_vertical
|
|
||||||
|
if has_explicit_width:
|
||||||
|
margin_container.size_flags_horizontal = node.size_flags_horizontal
|
||||||
|
else:
|
||||||
|
margin_container.size_flags_horizontal = node.size_flags_horizontal
|
||||||
|
node.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
|
|
||||||
|
if has_explicit_height:
|
||||||
|
margin_container.size_flags_vertical = node.size_flags_vertical
|
||||||
|
else:
|
||||||
|
margin_container.size_flags_vertical = node.size_flags_vertical
|
||||||
|
node.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||||
|
|
||||||
apply_margin_styles_to_container(margin_container, styles)
|
apply_margin_styles_to_container(margin_container, styles)
|
||||||
|
|
||||||
# Reset the original node's size flags since they're now handled by the wrapper
|
|
||||||
node.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
||||||
node.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
|
||||||
|
|
||||||
# Handle reparenting properly
|
# Handle reparenting properly
|
||||||
var original_parent = node.get_parent()
|
var original_parent = node.get_parent()
|
||||||
if original_parent:
|
if original_parent:
|
||||||
@@ -542,9 +549,22 @@ static func parse_radius(radius_str: String) -> int:
|
|||||||
|
|
||||||
static func apply_font_to_label(label: RichTextLabel, font_resource: Font) -> void:
|
static func apply_font_to_label(label: RichTextLabel, font_resource: Font) -> void:
|
||||||
label.add_theme_font_override("normal_font", font_resource)
|
label.add_theme_font_override("normal_font", font_resource)
|
||||||
label.add_theme_font_override("bold_font", font_resource)
|
|
||||||
label.add_theme_font_override("italics_font", font_resource)
|
var bold_font = SystemFont.new()
|
||||||
label.add_theme_font_override("bold_italics_font", font_resource)
|
bold_font.font_names = font_resource.font_names if font_resource is SystemFont else ["Arial"]
|
||||||
|
bold_font.font_weight = 700 # Bold weight
|
||||||
|
label.add_theme_font_override("bold_font", bold_font)
|
||||||
|
|
||||||
|
var italic_font = SystemFont.new()
|
||||||
|
italic_font.font_names = font_resource.font_names if font_resource is SystemFont else ["Arial"]
|
||||||
|
italic_font.font_italic = true
|
||||||
|
label.add_theme_font_override("italics_font", italic_font)
|
||||||
|
|
||||||
|
var bold_italic_font = SystemFont.new()
|
||||||
|
bold_italic_font.font_names = font_resource.font_names if font_resource is SystemFont else ["Arial"]
|
||||||
|
bold_italic_font.font_weight = 700 # Bold weight
|
||||||
|
bold_italic_font.font_italic = true
|
||||||
|
label.add_theme_font_override("bold_italics_font", bold_italic_font)
|
||||||
|
|
||||||
static func apply_font_to_button(button: Button, styles: Dictionary) -> void:
|
static func apply_font_to_button(button: Button, styles: Dictionary) -> void:
|
||||||
if styles.has("font-family"):
|
if styles.has("font-family"):
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ func set_icon(new_icon: Texture) -> void:
|
|||||||
icon.rotation = 0
|
icon.rotation = 0
|
||||||
|
|
||||||
func update_icon_from_url(icon_url: String) -> void:
|
func update_icon_from_url(icon_url: String) -> void:
|
||||||
|
if icon_url.is_empty():
|
||||||
|
stop_loading()
|
||||||
|
return
|
||||||
|
|
||||||
const LOADER_CIRCLE = preload("res://Assets/Icons/loader-circle.svg")
|
const LOADER_CIRCLE = preload("res://Assets/Icons/loader-circle.svg")
|
||||||
|
|
||||||
loading_tween = create_tween()
|
loading_tween = create_tween()
|
||||||
@@ -68,9 +72,7 @@ func update_icon_from_url(icon_url: String) -> void:
|
|||||||
# Only update if tab still exists
|
# Only update if tab still exists
|
||||||
if is_instance_valid(self):
|
if is_instance_valid(self):
|
||||||
set_icon(icon_resource)
|
set_icon(icon_resource)
|
||||||
if loading_tween:
|
stop_loading()
|
||||||
loading_tween.kill()
|
|
||||||
loading_tween = null
|
|
||||||
|
|
||||||
func _on_button_mouse_entered() -> void:
|
func _on_button_mouse_entered() -> void:
|
||||||
mouse_over_tab = true
|
mouse_over_tab = true
|
||||||
@@ -82,6 +84,27 @@ func _on_button_mouse_exited() -> void:
|
|||||||
if is_active: return
|
if is_active: return
|
||||||
gradient_texture.texture = TAB_GRADIENT_DEFAULT
|
gradient_texture.texture = TAB_GRADIENT_DEFAULT
|
||||||
|
|
||||||
|
func start_loading() -> void:
|
||||||
|
const LOADER_CIRCLE = preload("res://Assets/Icons/loader-circle.svg")
|
||||||
|
|
||||||
|
stop_loading()
|
||||||
|
|
||||||
|
loading_tween = create_tween()
|
||||||
|
set_icon(LOADER_CIRCLE)
|
||||||
|
loading_tween.set_loops()
|
||||||
|
icon.pivot_offset = Vector2(11.5, 11.5)
|
||||||
|
loading_tween.tween_method(func(angle):
|
||||||
|
if !is_instance_valid(icon):
|
||||||
|
if loading_tween: loading_tween.kill()
|
||||||
|
return
|
||||||
|
icon.rotation = angle
|
||||||
|
, 0.0, TAU, 1.0)
|
||||||
|
|
||||||
|
func stop_loading() -> void:
|
||||||
|
if loading_tween:
|
||||||
|
loading_tween.kill()
|
||||||
|
loading_tween = null
|
||||||
|
|
||||||
func _exit_tree():
|
func _exit_tree():
|
||||||
if loading_tween:
|
if loading_tween:
|
||||||
loading_tween.kill()
|
loading_tween.kill()
|
||||||
|
|||||||
@@ -189,10 +189,23 @@ func apply_padding_to_stylebox(style_box: StyleBoxFlat, styles: Dictionary) -> v
|
|||||||
|
|
||||||
func apply_size_and_flags(ctrl: Control, width: Variant, height: Variant) -> void:
|
func apply_size_and_flags(ctrl: Control, width: Variant, height: Variant) -> void:
|
||||||
if width != null or height != null:
|
if width != null or height != null:
|
||||||
ctrl.custom_minimum_size = Vector2(
|
var new_width = 0
|
||||||
width if width != null else 0,
|
var new_height = 0
|
||||||
height if height != null else 0
|
|
||||||
)
|
if width != null:
|
||||||
|
if SizingUtils.is_percentage(width):
|
||||||
|
new_width = SizingUtils.calculate_percentage_size(width, SizingUtils.DEFAULT_VIEWPORT_WIDTH)
|
||||||
|
else:
|
||||||
|
new_width = width
|
||||||
|
|
||||||
|
if height != null:
|
||||||
|
if SizingUtils.is_percentage(height):
|
||||||
|
new_height = SizingUtils.calculate_percentage_size(height, SizingUtils.DEFAULT_VIEWPORT_HEIGHT)
|
||||||
|
else:
|
||||||
|
new_height = height
|
||||||
|
|
||||||
|
ctrl.custom_minimum_size = Vector2(new_width, new_height)
|
||||||
|
|
||||||
if width != null:
|
if width != null:
|
||||||
ctrl.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
|
ctrl.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
|
||||||
if height != null:
|
if height != null:
|
||||||
|
|||||||
@@ -404,10 +404,22 @@ func apply_input_styles(element: HTMLParser.HTMLElement, parser: HTMLParser) ->
|
|||||||
if active_child:
|
if active_child:
|
||||||
if width or height:
|
if width or height:
|
||||||
# Explicit sizing from CSS
|
# Explicit sizing from CSS
|
||||||
var new_child_size = Vector2(
|
var new_width = active_child.custom_minimum_size.x
|
||||||
width if width else active_child.custom_minimum_size.x,
|
var new_height = max(active_child.custom_minimum_size.y, active_child.size.y)
|
||||||
height if height else max(active_child.custom_minimum_size.y, active_child.size.y)
|
|
||||||
)
|
if width:
|
||||||
|
if SizingUtils.is_percentage(width):
|
||||||
|
new_width = SizingUtils.calculate_percentage_size(width, SizingUtils.DEFAULT_VIEWPORT_WIDTH)
|
||||||
|
else:
|
||||||
|
new_width = width
|
||||||
|
|
||||||
|
if height:
|
||||||
|
if SizingUtils.is_percentage(height):
|
||||||
|
new_height = SizingUtils.calculate_percentage_size(height, SizingUtils.DEFAULT_VIEWPORT_HEIGHT)
|
||||||
|
else:
|
||||||
|
new_height = height
|
||||||
|
|
||||||
|
var new_child_size = Vector2(new_width, new_height)
|
||||||
|
|
||||||
active_child.custom_minimum_size = new_child_size
|
active_child.custom_minimum_size = new_child_size
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,38 @@ func init(element: HTMLParser.HTMLElement, parser: HTMLParser) -> void:
|
|||||||
# Allow mouse events to pass through to parent containers for hover effects while keeping text selection
|
# Allow mouse events to pass through to parent containers for hover effects while keeping text selection
|
||||||
mouse_filter = Control.MOUSE_FILTER_PASS
|
mouse_filter = Control.MOUSE_FILTER_PASS
|
||||||
|
|
||||||
# NOTE: estimate width/height because FlexContainer removes our anchor preset (sets 0 width)
|
autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||||
var plain_text = element.get_collapsed_text()
|
|
||||||
var estimated_height = 30
|
|
||||||
var estimated_width = min(200, max(100, plain_text.length() * 12))
|
|
||||||
|
|
||||||
custom_minimum_size = Vector2(estimated_width, estimated_height)
|
call_deferred("_auto_resize_to_content")
|
||||||
|
|
||||||
|
size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
|
set_anchors_and_offsets_preset(Control.PRESET_TOP_WIDE)
|
||||||
|
|
||||||
|
func _auto_resize_to_content():
|
||||||
|
if not is_inside_tree():
|
||||||
|
await tree_entered
|
||||||
|
|
||||||
|
var min_width = 20
|
||||||
|
var max_width = 800
|
||||||
|
var min_height = 30
|
||||||
|
|
||||||
|
fit_content = true
|
||||||
|
|
||||||
|
var original_autowrap = autowrap_mode
|
||||||
|
autowrap_mode = TextServer.AUTOWRAP_OFF
|
||||||
|
|
||||||
|
await get_tree().process_frame
|
||||||
|
|
||||||
|
var natural_width = size.x
|
||||||
|
var desired_width = clampf(natural_width, min_width, max_width)
|
||||||
|
|
||||||
|
autowrap_mode = original_autowrap
|
||||||
|
|
||||||
|
await get_tree().process_frame
|
||||||
|
|
||||||
|
var content_height = get_content_height()
|
||||||
|
var explicit_height = custom_minimum_size.y if custom_minimum_size.y > 0 else null
|
||||||
|
var final_height = explicit_height if explicit_height != null else max(content_height, min_height)
|
||||||
|
custom_minimum_size = Vector2(desired_width, final_height)
|
||||||
|
|
||||||
|
queue_redraw()
|
||||||
|
|||||||
39
flumi/Scripts/history.gd
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
extends MarginContainer
|
||||||
|
|
||||||
|
@onready var history_entry_container: VBoxContainer = $Main/PanelContainer2/ScrollContainer/HistoryEntryContainer
|
||||||
|
@onready var delete_menu: PanelContainer = $Main/DeleteMenu
|
||||||
|
@onready var line_edit: LineEdit = $Main/LineEdit
|
||||||
|
@onready var entries_label: RichTextLabel = $Main/DeleteMenu/HBoxContainer/RichTextLabel
|
||||||
|
@onready var cancel_button: Button = $Main/DeleteMenu/HBoxContainer/CancelButton
|
||||||
|
|
||||||
|
var toggled_entries = []
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
for entry in history_entry_container.get_children():
|
||||||
|
entry.connect("checkbox_toggle", history_toggle.bind(entry))
|
||||||
|
|
||||||
|
func history_toggle(toggled: bool, entry) -> void:
|
||||||
|
print('toggling ', entry, ' to :', toggled)
|
||||||
|
if toggled:
|
||||||
|
toggled_entries.append(entry)
|
||||||
|
else:
|
||||||
|
toggled_entries.remove_at(toggled_entries.find(entry))
|
||||||
|
|
||||||
|
entries_label.text = str(toggled_entries.size()) + " selected"
|
||||||
|
|
||||||
|
if toggled_entries.size() != 0:
|
||||||
|
delete_menu.show()
|
||||||
|
line_edit.hide()
|
||||||
|
else:
|
||||||
|
delete_menu.hide()
|
||||||
|
line_edit.show()
|
||||||
|
|
||||||
|
func _on_cancel_button_pressed() -> void:
|
||||||
|
var entries_to_reset = toggled_entries.duplicate()
|
||||||
|
toggled_entries.clear()
|
||||||
|
|
||||||
|
for entry in entries_to_reset:
|
||||||
|
entry.reset()
|
||||||
|
|
||||||
|
delete_menu.hide()
|
||||||
|
line_edit.show()
|
||||||
1
flumi/Scripts/history.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://ektopbvnhfga
|
||||||
10
flumi/Scripts/history_entry.gd
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
extends HBoxContainer
|
||||||
|
signal checkbox_toggle
|
||||||
|
|
||||||
|
@onready var check_box: CheckBox = $CheckBox
|
||||||
|
|
||||||
|
func reset() -> void:
|
||||||
|
check_box.set_pressed_no_signal(false)
|
||||||
|
|
||||||
|
func _on_check_box_toggled(toggled_on: bool) -> void:
|
||||||
|
checkbox_toggle.emit(toggled_on)
|
||||||
1
flumi/Scripts/history_entry.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://bw5pr4wrf780h
|
||||||
@@ -4,6 +4,8 @@ extends Control
|
|||||||
@onready var website_container: Control = %WebsiteContainer
|
@onready var website_container: Control = %WebsiteContainer
|
||||||
@onready var website_background: Control = %WebsiteBackground
|
@onready var website_background: Control = %WebsiteBackground
|
||||||
@onready var tab_container: TabManager = $VBoxContainer/TabContainer
|
@onready var tab_container: TabManager = $VBoxContainer/TabContainer
|
||||||
|
@onready var search_bar: LineEdit = $VBoxContainer/HBoxContainer/LineEdit
|
||||||
|
|
||||||
const LOADER_CIRCLE = preload("res://Assets/Icons/loader-circle.svg")
|
const LOADER_CIRCLE = preload("res://Assets/Icons/loader-circle.svg")
|
||||||
const AUTO_SIZING_FLEX_CONTAINER = preload("res://Scripts/AutoSizingFlexContainer.gd")
|
const AUTO_SIZING_FLEX_CONTAINER = preload("res://Scripts/AutoSizingFlexContainer.gd")
|
||||||
|
|
||||||
@@ -54,6 +56,8 @@ func _ready():
|
|||||||
|
|
||||||
get_viewport().size_changed.connect(_on_viewport_size_changed)
|
get_viewport().size_changed.connect(_on_viewport_size_changed)
|
||||||
|
|
||||||
|
call_deferred("render")
|
||||||
|
|
||||||
func _on_viewport_size_changed():
|
func _on_viewport_size_changed():
|
||||||
recalculate_percentage_elements(website_container)
|
recalculate_percentage_elements(website_container)
|
||||||
|
|
||||||
@@ -64,7 +68,49 @@ func recalculate_percentage_elements(node: Node):
|
|||||||
for child in node.get_children():
|
for child in node.get_children():
|
||||||
recalculate_percentage_elements(child)
|
recalculate_percentage_elements(child)
|
||||||
|
|
||||||
|
var current_domain = "" # Store current domain for display
|
||||||
|
|
||||||
|
func _on_search_submitted(url: String) -> void:
|
||||||
|
print("Search submitted: ", url)
|
||||||
|
|
||||||
|
if GurtProtocol.is_gurt_domain(url):
|
||||||
|
print("Processing as GURT domain")
|
||||||
|
|
||||||
|
var tab = tab_container.tabs[tab_container.active_tab]
|
||||||
|
tab.start_loading()
|
||||||
|
|
||||||
|
var result = await GurtProtocol.handle_gurt_domain(url)
|
||||||
|
|
||||||
|
if result.has("error"):
|
||||||
|
print("GURT domain error: ", result.error)
|
||||||
|
const GLOBE_ICON = preload("res://Assets/Icons/globe.svg")
|
||||||
|
tab.stop_loading()
|
||||||
|
tab.set_icon(GLOBE_ICON)
|
||||||
|
|
||||||
|
var html_bytes = result.html.to_utf8_buffer()
|
||||||
|
render_content(html_bytes)
|
||||||
|
|
||||||
|
if result.has("display_url"):
|
||||||
|
current_domain = result.display_url
|
||||||
|
if not search_bar.has_focus():
|
||||||
|
search_bar.text = current_domain
|
||||||
|
else:
|
||||||
|
print("Non-GURT URL entered: ", url)
|
||||||
|
|
||||||
|
func _on_search_focus_entered() -> void:
|
||||||
|
if not current_domain.is_empty():
|
||||||
|
search_bar.text = "gurt://" + current_domain
|
||||||
|
|
||||||
|
func _on_search_focus_exited() -> void:
|
||||||
|
if not current_domain.is_empty():
|
||||||
|
search_bar.text = current_domain
|
||||||
|
|
||||||
|
|
||||||
func render() -> void:
|
func render() -> void:
|
||||||
|
render_content(Constants.HTML_CONTENT)
|
||||||
|
|
||||||
|
func render_content(html_bytes: PackedByteArray) -> void:
|
||||||
|
|
||||||
# Clear existing content
|
# Clear existing content
|
||||||
for child in website_container.get_children():
|
for child in website_container.get_children():
|
||||||
child.queue_free()
|
child.queue_free()
|
||||||
@@ -73,8 +119,6 @@ func render() -> void:
|
|||||||
FontManager.clear_fonts()
|
FontManager.clear_fonts()
|
||||||
FontManager.set_refresh_callback(refresh_fonts)
|
FontManager.set_refresh_callback(refresh_fonts)
|
||||||
|
|
||||||
var html_bytes = Constants.HTML_CONTENT
|
|
||||||
|
|
||||||
var parser: HTMLParser = HTMLParser.new(html_bytes)
|
var parser: HTMLParser = HTMLParser.new(html_bytes)
|
||||||
var parse_result = parser.parse()
|
var parse_result = parser.parse()
|
||||||
|
|
||||||
@@ -109,57 +153,59 @@ func render() -> void:
|
|||||||
add_child(lua_api)
|
add_child(lua_api)
|
||||||
|
|
||||||
var i = 0
|
var i = 0
|
||||||
while i < body.children.size():
|
if body:
|
||||||
var element: HTMLParser.HTMLElement = body.children[i]
|
while i < body.children.size():
|
||||||
|
var element: HTMLParser.HTMLElement = body.children[i]
|
||||||
|
|
||||||
if should_group_as_inline(element):
|
if should_group_as_inline(element):
|
||||||
# Create an HBoxContainer for consecutive inline elements
|
# Create an HBoxContainer for consecutive inline elements
|
||||||
var inline_elements: Array[HTMLParser.HTMLElement] = []
|
var inline_elements: Array[HTMLParser.HTMLElement] = []
|
||||||
|
|
||||||
while i < body.children.size() and should_group_as_inline(body.children[i]):
|
while i < body.children.size() and should_group_as_inline(body.children[i]):
|
||||||
inline_elements.append(body.children[i])
|
inline_elements.append(body.children[i])
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
var hbox = HBoxContainer.new()
|
var hbox = HBoxContainer.new()
|
||||||
hbox.add_theme_constant_override("separation", 4)
|
hbox.add_theme_constant_override("separation", 4)
|
||||||
|
|
||||||
for inline_element in inline_elements:
|
for inline_element in inline_elements:
|
||||||
var inline_node = await create_element_node(inline_element, parser)
|
var inline_node = await create_element_node(inline_element, parser)
|
||||||
if inline_node:
|
if inline_node:
|
||||||
# Input elements register their own DOM nodes in their init() function
|
|
||||||
if inline_element.tag_name not in ["input", "textarea", "select", "button", "audio"]:
|
|
||||||
parser.register_dom_node(inline_element, inline_node)
|
|
||||||
|
|
||||||
safe_add_child(hbox, inline_node)
|
# Input elements register their own DOM nodes in their init() function
|
||||||
# Handle hyperlinks for all inline elements
|
if inline_element.tag_name not in ["input", "textarea", "select", "button", "audio"]:
|
||||||
if contains_hyperlink(inline_element) and inline_node is RichTextLabel:
|
parser.register_dom_node(inline_element, inline_node)
|
||||||
inline_node.meta_clicked.connect(func(meta): OS.shell_open(str(meta)))
|
|
||||||
else:
|
|
||||||
print("Failed to create inline element node: ", inline_element.tag_name)
|
|
||||||
|
|
||||||
safe_add_child(website_container, hbox)
|
safe_add_child(hbox, inline_node)
|
||||||
continue
|
# Handle hyperlinks for all inline elements
|
||||||
|
if contains_hyperlink(inline_element) and inline_node is RichTextLabel:
|
||||||
|
inline_node.meta_clicked.connect(func(meta): OS.shell_open(str(meta)))
|
||||||
|
else:
|
||||||
|
print("Failed to create inline element node: ", inline_element.tag_name)
|
||||||
|
|
||||||
var element_node = await create_element_node(element, parser)
|
safe_add_child(website_container, hbox)
|
||||||
if element_node:
|
continue
|
||||||
# Input elements register their own DOM nodes in their init() function
|
|
||||||
if element.tag_name not in ["input", "textarea", "select", "button", "audio"]:
|
|
||||||
parser.register_dom_node(element, element_node)
|
|
||||||
|
|
||||||
# ul/ol handle their own adding
|
var element_node = await create_element_node(element, parser)
|
||||||
if element.tag_name != "ul" and element.tag_name != "ol":
|
if element_node:
|
||||||
safe_add_child(website_container, element_node)
|
|
||||||
|
|
||||||
# Handle hyperlinks for all elements
|
# Input elements register their own DOM nodes in their init() function
|
||||||
if contains_hyperlink(element):
|
if element.tag_name not in ["input", "textarea", "select", "button", "audio"]:
|
||||||
if element_node is RichTextLabel:
|
parser.register_dom_node(element, element_node)
|
||||||
element_node.meta_clicked.connect(func(meta): OS.shell_open(str(meta)))
|
|
||||||
elif element_node.has_method("get") and element_node.get("rich_text_label"):
|
|
||||||
element_node.rich_text_label.meta_clicked.connect(func(meta): OS.shell_open(str(meta)))
|
|
||||||
else:
|
|
||||||
print("Couldn't parse unsupported HTML tag \"%s\"" % element.tag_name)
|
|
||||||
|
|
||||||
i += 1
|
# ul/ol handle their own adding
|
||||||
|
if element.tag_name != "ul" and element.tag_name != "ol":
|
||||||
|
safe_add_child(website_container, element_node)
|
||||||
|
|
||||||
|
if contains_hyperlink(element):
|
||||||
|
if element_node is RichTextLabel:
|
||||||
|
element_node.meta_clicked.connect(func(meta): OS.shell_open(str(meta)))
|
||||||
|
elif element_node.has_method("get") and element_node.get("rich_text_label"):
|
||||||
|
element_node.rich_text_label.meta_clicked.connect(func(meta): OS.shell_open(str(meta)))
|
||||||
|
else:
|
||||||
|
print("Couldn't parse unsupported HTML tag \"%s\"" % element.tag_name)
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
|
||||||
if scripts.size() > 0 and lua_api:
|
if scripts.size() > 0 and lua_api:
|
||||||
parser.process_scripts(lua_api, null)
|
parser.process_scripts(lua_api, null)
|
||||||
@@ -381,6 +427,9 @@ func create_element_node_internal(element: HTMLParser.HTMLElement, parser: HTMLP
|
|||||||
var p_node = P.instantiate()
|
var p_node = P.instantiate()
|
||||||
p_node.init(element, parser)
|
p_node.init(element, parser)
|
||||||
|
|
||||||
|
var div_styles = parser.get_element_styles_with_inheritance(element, "", [])
|
||||||
|
StyleManager.apply_styles_to_label(p_node, div_styles, element, parser)
|
||||||
|
|
||||||
var container_for_children = node
|
var container_for_children = node
|
||||||
if node is PanelContainer and node.get_child_count() > 0:
|
if node is PanelContainer and node.get_child_count() > 0:
|
||||||
container_for_children = node.get_child(0) # The VBoxContainer inside
|
container_for_children = node.get_child(0) # The VBoxContainer inside
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ folder_colors={
|
|||||||
"res://Scripts/": "blue"
|
"res://Scripts/": "blue"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[gui]
|
||||||
|
|
||||||
|
theme/custom_font="uid://fij84uxfqh4h"
|
||||||
|
|
||||||
[input]
|
[input]
|
||||||
|
|
||||||
NewTab={
|
NewTab={
|
||||||
|
|||||||