init
This commit is contained in:
commit
541646b135
|
|
@ -0,0 +1,12 @@
|
|||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
/dist/
|
||||
/static/
|
||||
/.dioxus/
|
||||
|
||||
# this file will generate by tailwind:
|
||||
/assets/tailwind.css
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Debug executable 'fast-log-viewer'",
|
||||
"cargo": {
|
||||
"args": [
|
||||
"build",
|
||||
"--bin=fast-log-viewer",
|
||||
"--package=fast-log-viewer"
|
||||
],
|
||||
"filter": {
|
||||
"name": "fast-log-viewer",
|
||||
"kind": "bin"
|
||||
}
|
||||
},
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Debug unit tests in executable 'fast-log-viewer'",
|
||||
"cargo": {
|
||||
"args": [
|
||||
"test",
|
||||
"--no-run",
|
||||
"--bin=fast-log-viewer",
|
||||
"--package=fast-log-viewer"
|
||||
],
|
||||
"filter": {
|
||||
"name": "fast-log-viewer",
|
||||
"kind": "bin"
|
||||
}
|
||||
},
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,15 @@
|
|||
[package]
|
||||
name = "fast-log-viewer"
|
||||
version = "0.1.0"
|
||||
authors = ["hardliner66 <hardliner66@gmail.com>"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.5.19", features = ["derive"] }
|
||||
dioxus = { version = "0.5", features = ["desktop", "router"] }
|
||||
dioxus-logger = "0.5.1"
|
||||
manganis = "0.2.2"
|
||||
regex = "1.11.0"
|
||||
|
||||
[features]
|
||||
bundle = []
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
[application]
|
||||
|
||||
# App (Project) Name
|
||||
name = "fast-log-viewer"
|
||||
|
||||
# Dioxus App Default Platform
|
||||
# web, desktop, fullstack
|
||||
default_platform = "desktop"
|
||||
|
||||
# `build` & `serve` dist path
|
||||
out_dir = "dist"
|
||||
|
||||
# assets file folder
|
||||
asset_dir = "assets"
|
||||
|
||||
[web.app]
|
||||
|
||||
# HTML title tag content
|
||||
title = "fast-log-viewer"
|
||||
|
||||
[web.watcher]
|
||||
|
||||
# when watcher trigger, regenerate the `index.html`
|
||||
reload_html = true
|
||||
|
||||
# which files or dirs will be watcher monitoring
|
||||
watch_path = ["src", "assets"]
|
||||
|
||||
# include `assets` in web platform
|
||||
[web.resource]
|
||||
|
||||
# CSS style file
|
||||
|
||||
style = ["/assets/tailwind.css"]
|
||||
|
||||
# Javascript code file
|
||||
script = []
|
||||
|
||||
[web.resource.dev]
|
||||
|
||||
# Javascript code file
|
||||
# serve: [dev-server] only
|
||||
script = []
|
||||
|
||||
[bundle]
|
||||
# The list of files to include in the bundle. These can contain globs.
|
||||
resources = ["assets/**/*"]
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# Development
|
||||
|
||||
1. Install npm: https://docs.npmjs.com/downloading-and-installing-node-js-and-npm
|
||||
2. Install the tailwind css cli: https://tailwindcss.com/docs/installation
|
||||
3. Run the following command in the root of the project to start the tailwind CSS compiler:
|
||||
|
||||
```bash
|
||||
npx tailwindcss -i ./input.css -o ./assets/tailwind.css --watch
|
||||
```
|
||||
|
||||
Run the following command in the root of the project to start the Dioxus dev server:
|
||||
|
||||
```bash
|
||||
dx serve --hot-reload --platform desktop
|
||||
```
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 130 KiB |
|
|
@ -0,0 +1,48 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
th {
|
||||
border-color: black;
|
||||
@apply border px-4 py-2;
|
||||
}
|
||||
|
||||
td {
|
||||
@apply border px-4 py-2;
|
||||
@apply text-ellipsis overflow-hidden;
|
||||
}
|
||||
|
||||
td div{
|
||||
@apply text-ellipsis overflow-hidden;
|
||||
}
|
||||
|
||||
/* Ensure the body and html take up the full height */
|
||||
html, body {
|
||||
height: 100vh;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Parent container as a flex container */
|
||||
.p-4 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden; /* Prevents scrollbar on the body */
|
||||
}
|
||||
|
||||
/* Header stays at the top */
|
||||
.header {
|
||||
position: fixed;
|
||||
/* Set height as needed */
|
||||
max-height: 80px; /* Adjust to your header's height */
|
||||
background-color: white; /* Optional */
|
||||
}
|
||||
|
||||
/* Content area fills the remaining space and is scrollable */
|
||||
.content {
|
||||
position: fixed;
|
||||
max-height: calc(100vh - 90px); /* Adjust to your header's height */
|
||||
max-width: calc(100vw - 20px);
|
||||
overflow-y: scroll;
|
||||
overflow-x: scroll;
|
||||
top: 80px;
|
||||
}
|
||||
|
|
@ -0,0 +1,675 @@
|
|||
*, ::before, ::after {
|
||||
--tw-border-spacing-x: 0;
|
||||
--tw-border-spacing-y: 0;
|
||||
--tw-translate-x: 0;
|
||||
--tw-translate-y: 0;
|
||||
--tw-rotate: 0;
|
||||
--tw-skew-x: 0;
|
||||
--tw-skew-y: 0;
|
||||
--tw-scale-x: 1;
|
||||
--tw-scale-y: 1;
|
||||
--tw-pan-x: ;
|
||||
--tw-pan-y: ;
|
||||
--tw-pinch-zoom: ;
|
||||
--tw-scroll-snap-strictness: proximity;
|
||||
--tw-gradient-from-position: ;
|
||||
--tw-gradient-via-position: ;
|
||||
--tw-gradient-to-position: ;
|
||||
--tw-ordinal: ;
|
||||
--tw-slashed-zero: ;
|
||||
--tw-numeric-figure: ;
|
||||
--tw-numeric-spacing: ;
|
||||
--tw-numeric-fraction: ;
|
||||
--tw-ring-inset: ;
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgb(59 130 246 / 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-shadow-colored: 0 0 #0000;
|
||||
--tw-blur: ;
|
||||
--tw-brightness: ;
|
||||
--tw-contrast: ;
|
||||
--tw-grayscale: ;
|
||||
--tw-hue-rotate: ;
|
||||
--tw-invert: ;
|
||||
--tw-saturate: ;
|
||||
--tw-sepia: ;
|
||||
--tw-drop-shadow: ;
|
||||
--tw-backdrop-blur: ;
|
||||
--tw-backdrop-brightness: ;
|
||||
--tw-backdrop-contrast: ;
|
||||
--tw-backdrop-grayscale: ;
|
||||
--tw-backdrop-hue-rotate: ;
|
||||
--tw-backdrop-invert: ;
|
||||
--tw-backdrop-opacity: ;
|
||||
--tw-backdrop-saturate: ;
|
||||
--tw-backdrop-sepia: ;
|
||||
--tw-contain-size: ;
|
||||
--tw-contain-layout: ;
|
||||
--tw-contain-paint: ;
|
||||
--tw-contain-style: ;
|
||||
}
|
||||
|
||||
::backdrop {
|
||||
--tw-border-spacing-x: 0;
|
||||
--tw-border-spacing-y: 0;
|
||||
--tw-translate-x: 0;
|
||||
--tw-translate-y: 0;
|
||||
--tw-rotate: 0;
|
||||
--tw-skew-x: 0;
|
||||
--tw-skew-y: 0;
|
||||
--tw-scale-x: 1;
|
||||
--tw-scale-y: 1;
|
||||
--tw-pan-x: ;
|
||||
--tw-pan-y: ;
|
||||
--tw-pinch-zoom: ;
|
||||
--tw-scroll-snap-strictness: proximity;
|
||||
--tw-gradient-from-position: ;
|
||||
--tw-gradient-via-position: ;
|
||||
--tw-gradient-to-position: ;
|
||||
--tw-ordinal: ;
|
||||
--tw-slashed-zero: ;
|
||||
--tw-numeric-figure: ;
|
||||
--tw-numeric-spacing: ;
|
||||
--tw-numeric-fraction: ;
|
||||
--tw-ring-inset: ;
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgb(59 130 246 / 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-shadow-colored: 0 0 #0000;
|
||||
--tw-blur: ;
|
||||
--tw-brightness: ;
|
||||
--tw-contrast: ;
|
||||
--tw-grayscale: ;
|
||||
--tw-hue-rotate: ;
|
||||
--tw-invert: ;
|
||||
--tw-saturate: ;
|
||||
--tw-sepia: ;
|
||||
--tw-drop-shadow: ;
|
||||
--tw-backdrop-blur: ;
|
||||
--tw-backdrop-brightness: ;
|
||||
--tw-backdrop-contrast: ;
|
||||
--tw-backdrop-grayscale: ;
|
||||
--tw-backdrop-hue-rotate: ;
|
||||
--tw-backdrop-invert: ;
|
||||
--tw-backdrop-opacity: ;
|
||||
--tw-backdrop-saturate: ;
|
||||
--tw-backdrop-sepia: ;
|
||||
--tw-contain-size: ;
|
||||
--tw-contain-layout: ;
|
||||
--tw-contain-paint: ;
|
||||
--tw-contain-style: ;
|
||||
}
|
||||
|
||||
/*
|
||||
! tailwindcss v3.4.13 | MIT License | https://tailwindcss.com
|
||||
*/
|
||||
|
||||
/*
|
||||
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
|
||||
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
|
||||
*/
|
||||
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
box-sizing: border-box;
|
||||
/* 1 */
|
||||
border-width: 0;
|
||||
/* 2 */
|
||||
border-style: solid;
|
||||
/* 2 */
|
||||
border-color: #e5e7eb;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
::before,
|
||||
::after {
|
||||
--tw-content: '';
|
||||
}
|
||||
|
||||
/*
|
||||
1. Use a consistent sensible line-height in all browsers.
|
||||
2. Prevent adjustments of font size after orientation changes in iOS.
|
||||
3. Use a more readable tab size.
|
||||
4. Use the user's configured `sans` font-family by default.
|
||||
5. Use the user's configured `sans` font-feature-settings by default.
|
||||
6. Use the user's configured `sans` font-variation-settings by default.
|
||||
7. Disable tap highlights on iOS
|
||||
*/
|
||||
|
||||
html,
|
||||
:host {
|
||||
line-height: 1.5;
|
||||
/* 1 */
|
||||
-webkit-text-size-adjust: 100%;
|
||||
/* 2 */
|
||||
-moz-tab-size: 4;
|
||||
/* 3 */
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
/* 3 */
|
||||
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
/* 4 */
|
||||
font-feature-settings: normal;
|
||||
/* 5 */
|
||||
font-variation-settings: normal;
|
||||
/* 6 */
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
/* 7 */
|
||||
}
|
||||
|
||||
/*
|
||||
1. Remove the margin in all browsers.
|
||||
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
/* 1 */
|
||||
line-height: inherit;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
1. Add the correct height in Firefox.
|
||||
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
|
||||
3. Ensure horizontal rules are visible by default.
|
||||
*/
|
||||
|
||||
hr {
|
||||
height: 0;
|
||||
/* 1 */
|
||||
color: inherit;
|
||||
/* 2 */
|
||||
border-top-width: 1px;
|
||||
/* 3 */
|
||||
}
|
||||
|
||||
/*
|
||||
Add the correct text decoration in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
abbr:where([title]) {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
}
|
||||
|
||||
/*
|
||||
Remove the default font size and weight for headings.
|
||||
*/
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
/*
|
||||
Reset links to optimize for opt-in styling instead of opt-out.
|
||||
*/
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
/*
|
||||
Add the correct font weight in Edge and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/*
|
||||
1. Use the user's configured `mono` font-family by default.
|
||||
2. Use the user's configured `mono` font-feature-settings by default.
|
||||
3. Use the user's configured `mono` font-variation-settings by default.
|
||||
4. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp,
|
||||
pre {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
/* 1 */
|
||||
font-feature-settings: normal;
|
||||
/* 2 */
|
||||
font-variation-settings: normal;
|
||||
/* 3 */
|
||||
font-size: 1em;
|
||||
/* 4 */
|
||||
}
|
||||
|
||||
/*
|
||||
Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/*
|
||||
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/*
|
||||
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
|
||||
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
|
||||
3. Remove gaps between table borders by default.
|
||||
*/
|
||||
|
||||
table {
|
||||
text-indent: 0;
|
||||
/* 1 */
|
||||
border-color: inherit;
|
||||
/* 2 */
|
||||
border-collapse: collapse;
|
||||
/* 3 */
|
||||
}
|
||||
|
||||
/*
|
||||
1. Change the font styles in all browsers.
|
||||
2. Remove the margin in Firefox and Safari.
|
||||
3. Remove default padding in all browsers.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit;
|
||||
/* 1 */
|
||||
font-feature-settings: inherit;
|
||||
/* 1 */
|
||||
font-variation-settings: inherit;
|
||||
/* 1 */
|
||||
font-size: 100%;
|
||||
/* 1 */
|
||||
font-weight: inherit;
|
||||
/* 1 */
|
||||
line-height: inherit;
|
||||
/* 1 */
|
||||
letter-spacing: inherit;
|
||||
/* 1 */
|
||||
color: inherit;
|
||||
/* 1 */
|
||||
margin: 0;
|
||||
/* 2 */
|
||||
padding: 0;
|
||||
/* 3 */
|
||||
}
|
||||
|
||||
/*
|
||||
Remove the inheritance of text transform in Edge and Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/*
|
||||
1. Correct the inability to style clickable types in iOS and Safari.
|
||||
2. Remove default button styles.
|
||||
*/
|
||||
|
||||
button,
|
||||
input:where([type='button']),
|
||||
input:where([type='reset']),
|
||||
input:where([type='submit']) {
|
||||
-webkit-appearance: button;
|
||||
/* 1 */
|
||||
background-color: transparent;
|
||||
/* 2 */
|
||||
background-image: none;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
Use the modern Firefox focus style for all focusable elements.
|
||||
*/
|
||||
|
||||
:-moz-focusring {
|
||||
outline: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
|
||||
*/
|
||||
|
||||
:-moz-ui-invalid {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/*
|
||||
Add the correct vertical alignment in Chrome and Firefox.
|
||||
*/
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/*
|
||||
Correct the cursor style of increment and decrement buttons in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-inner-spin-button,
|
||||
::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
1. Correct the odd appearance in Chrome and Safari.
|
||||
2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type='search'] {
|
||||
-webkit-appearance: textfield;
|
||||
/* 1 */
|
||||
outline-offset: -2px;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
Remove the inner padding in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/*
|
||||
1. Correct the inability to style clickable types in iOS and Safari.
|
||||
2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button;
|
||||
/* 1 */
|
||||
font: inherit;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
Add the correct display in Chrome and Safari.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/*
|
||||
Removes the default spacing and border for appropriate elements.
|
||||
*/
|
||||
|
||||
blockquote,
|
||||
dl,
|
||||
dd,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
hr,
|
||||
figure,
|
||||
p,
|
||||
pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
menu {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Reset default styling for dialogs.
|
||||
*/
|
||||
|
||||
dialog {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Prevent resizing textareas horizontally by default.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
/*
|
||||
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
|
||||
2. Set the default placeholder color to the user's configured gray 400 color.
|
||||
*/
|
||||
|
||||
input::-moz-placeholder, textarea::-moz-placeholder {
|
||||
opacity: 1;
|
||||
/* 1 */
|
||||
color: #9ca3af;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
input::placeholder,
|
||||
textarea::placeholder {
|
||||
opacity: 1;
|
||||
/* 1 */
|
||||
color: #9ca3af;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
Set the default cursor for buttons.
|
||||
*/
|
||||
|
||||
button,
|
||||
[role="button"] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/*
|
||||
Make sure disabled buttons don't get the pointer cursor.
|
||||
*/
|
||||
|
||||
:disabled {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/*
|
||||
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
|
||||
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
|
||||
This can trigger a poorly considered lint error in some tools but is included by design.
|
||||
*/
|
||||
|
||||
img,
|
||||
svg,
|
||||
video,
|
||||
canvas,
|
||||
audio,
|
||||
iframe,
|
||||
embed,
|
||||
object {
|
||||
display: block;
|
||||
/* 1 */
|
||||
vertical-align: middle;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
|
||||
*/
|
||||
|
||||
img,
|
||||
video {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* Make elements with the HTML hidden attribute stay hidden by default */
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.visible {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.static {
|
||||
position: static;
|
||||
}
|
||||
|
||||
.absolute {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.relative {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.right-0 {
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.top-0 {
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.mb-4 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.mr-4 {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.table {
|
||||
display: table;
|
||||
}
|
||||
|
||||
.h-full {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.w-1 {
|
||||
width: 0.25rem;
|
||||
}
|
||||
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.table-auto {
|
||||
table-layout: auto;
|
||||
}
|
||||
|
||||
.cursor-col-resize {
|
||||
cursor: col-resize;
|
||||
}
|
||||
|
||||
.resize-x {
|
||||
resize: horizontal;
|
||||
}
|
||||
|
||||
.border {
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
.bg-gray-200 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.p-2 {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.p-4 {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.px-4 {
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
||||
.py-2 {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.text-blue-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(59 130 246 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-gray-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(107 114 128 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-red-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(239 68 68 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-yellow-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(234 179 8 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.filter {
|
||||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||
}
|
||||
|
||||
.hover\:bg-gray-100:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
|
@ -0,0 +1,379 @@
|
|||
#![allow(non_snake_case)]
|
||||
#![cfg_attr(target_os = "windows", windows_subsystem = "windows")]
|
||||
|
||||
use std::{fs::File, io::Read};
|
||||
|
||||
use clap::Parser;
|
||||
use dioxus::{desktop::WindowBuilder, prelude::*};
|
||||
use dioxus_logger::tracing::{info, Level};
|
||||
use regex::RegexBuilder;
|
||||
|
||||
#[derive(Clone, Parser)]
|
||||
struct Args {
|
||||
log_file: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct LogEntry {
|
||||
timestamp: String,
|
||||
level: LogLevel,
|
||||
category: String,
|
||||
thread: String,
|
||||
source: String,
|
||||
message: String,
|
||||
}
|
||||
|
||||
impl LogEntry {
|
||||
fn level_class(&self) -> &str {
|
||||
match self.level {
|
||||
LogLevel::Info => "text-blue-500",
|
||||
LogLevel::Warning => "text-yellow-500",
|
||||
LogLevel::Error => "text-red-500",
|
||||
_ => "text-gray-500",
|
||||
}
|
||||
}
|
||||
|
||||
fn matches_query(&self, query: &str) -> bool {
|
||||
let query = query.trim().to_lowercase();
|
||||
if query.is_empty() {
|
||||
return true;
|
||||
}
|
||||
self.timestamp.to_lowercase().contains(&query)
|
||||
|| self.level.as_str().to_lowercase().contains(&query)
|
||||
|| self.category.to_lowercase().contains(&query)
|
||||
|| self.thread.to_lowercase().contains(&query)
|
||||
|| self.source.to_lowercase().contains(&query)
|
||||
|| self.message.to_lowercase().contains(&query)
|
||||
}
|
||||
}
|
||||
|
||||
fn highlight_matches<'a>(text: &'a str, query: &str) -> Vec<(&'a str, bool)> {
|
||||
if query.is_empty() {
|
||||
return vec![(text, false)];
|
||||
}
|
||||
let mut result = Vec::new();
|
||||
let mut last_end = 0;
|
||||
|
||||
let re = RegexBuilder::new(®ex::escape(query))
|
||||
.case_insensitive(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
for mat in re.find_iter(text) {
|
||||
if mat.start() > last_end {
|
||||
result.push((&text[last_end..mat.start()], false));
|
||||
}
|
||||
result.push((&text[mat.start()..mat.end()], true));
|
||||
last_end = mat.end();
|
||||
}
|
||||
|
||||
if last_end < text.len() {
|
||||
result.push((&text[last_end..], false));
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
enum LogLevel {
|
||||
Trace,
|
||||
Debug,
|
||||
Info,
|
||||
Warning,
|
||||
Error,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl LogLevel {
|
||||
fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
LogLevel::Trace => "TRACE",
|
||||
LogLevel::Debug => "DEBUG",
|
||||
LogLevel::Info => "INFO",
|
||||
LogLevel::Warning => "WARN",
|
||||
LogLevel::Error => "ERROR",
|
||||
LogLevel::Unknown => "UNKNOWN",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for LogLevel {
|
||||
fn from(s: &str) -> Self {
|
||||
match s.to_uppercase().as_str() {
|
||||
"TRACE" => LogLevel::Trace,
|
||||
"DEBUG" => LogLevel::Debug,
|
||||
"INFO" => LogLevel::Info,
|
||||
"WARNING" => LogLevel::Warning,
|
||||
"ERROR" => LogLevel::Error,
|
||||
_ => LogLevel::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Routable, Debug, PartialEq)]
|
||||
enum Route {
|
||||
#[route("/")]
|
||||
Home {},
|
||||
}
|
||||
|
||||
fn make_config() -> dioxus::desktop::Config {
|
||||
// dioxus::desktop::Config::new()
|
||||
// .with_custom_head(r#"<script src="/assets/tailwind.js"></script>"#.to_string())
|
||||
let cfg = dioxus::desktop::Config::new();
|
||||
#[cfg(not(debug_assertions))]
|
||||
let cfg = cfg.with_disable_context_menu(true);
|
||||
#[cfg(not(debug_assertions))]
|
||||
let cfg = cfg.with_menu(None);
|
||||
cfg.with_custom_head(r#"<link rel="stylesheet" href="assets/tailwind.css">"#.to_string())
|
||||
.with_window(make_window())
|
||||
}
|
||||
|
||||
fn make_window() -> WindowBuilder {
|
||||
WindowBuilder::new()
|
||||
.with_resizable(true)
|
||||
.with_always_on_top(false)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Init logger
|
||||
dioxus_logger::init(Level::ERROR).expect("failed to init logger");
|
||||
info!("starting app");
|
||||
|
||||
LaunchBuilder::desktop().with_cfg(make_config()).launch(App);
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn App() -> Element {
|
||||
rsx! {
|
||||
Router::<Route> {}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_log_file(content: &str) -> Vec<LogEntry> {
|
||||
let mut entries = Vec::new();
|
||||
for line in content.lines() {
|
||||
let parts: Vec<&str> = line.split('\t').collect();
|
||||
if parts.len() >= 6 {
|
||||
entries.push(LogEntry {
|
||||
timestamp: parts[0].to_string(),
|
||||
level: LogLevel::from(parts[1]),
|
||||
category: parts[2].to_string(),
|
||||
thread: parts[3].to_string(),
|
||||
source: parts[4].to_string(),
|
||||
message: parts[5..].join(" "),
|
||||
});
|
||||
}
|
||||
}
|
||||
entries
|
||||
}
|
||||
|
||||
fn read_log_file(filename: &str) -> Vec<LogEntry> {
|
||||
let mut entries = Vec::new();
|
||||
if let Ok(mut file) = File::open(filename) {
|
||||
let mut contents = String::new();
|
||||
if file.read_to_string(&mut contents).is_ok() {
|
||||
entries = parse_log_file(&contents);
|
||||
}
|
||||
}
|
||||
entries
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn Home() -> Element {
|
||||
let mut log_entries = use_signal(|| {
|
||||
let Args { log_file } = Args::parse();
|
||||
log_file
|
||||
.map(|log_file| read_log_file(&log_file))
|
||||
.unwrap_or_default()
|
||||
});
|
||||
|
||||
let mut search_query = use_signal(String::new);
|
||||
let mut highlight = use_signal(String::new);
|
||||
|
||||
// State for column widths
|
||||
let column_widths = [150.0, 80.0, 100.0, 140.0, 300.0, 150.0]; // Initial widths for 6 columns
|
||||
|
||||
// Columns visibility
|
||||
let mut column_visibility = use_signal(|| vec![true; 6]); // All columns visible by default
|
||||
|
||||
// Column titles
|
||||
let column_titles = [
|
||||
"Timestamp",
|
||||
"Level",
|
||||
"Category",
|
||||
"Thread",
|
||||
"Source",
|
||||
"Message",
|
||||
];
|
||||
|
||||
rsx! {
|
||||
div { class: "p-4",
|
||||
// Search input
|
||||
div {
|
||||
class: "header",
|
||||
div {
|
||||
style: "display: flex;",
|
||||
input {
|
||||
style: "flex: 1;",
|
||||
class: "border w-full mb-2",
|
||||
r#type: "text",
|
||||
value: "{search_query}",
|
||||
placeholder: "Search...",
|
||||
oninput: move |e| {
|
||||
search_query.set(e.value());
|
||||
}
|
||||
}
|
||||
input {
|
||||
style: "flex: 1; margin-left: 8px;",
|
||||
class: "border w-full mb-2",
|
||||
r#type: "text",
|
||||
value: "{highlight}",
|
||||
placeholder: "Highlight...",
|
||||
oninput: move |e| {
|
||||
highlight.set(e.value());
|
||||
}
|
||||
},
|
||||
input {
|
||||
id: "files",
|
||||
style: "display:none;",
|
||||
class: "hidden",
|
||||
r#type: "file",
|
||||
onchange: move |e| {
|
||||
async move {
|
||||
if let Some(file_engine) = e.files() {
|
||||
let files = file_engine.files();
|
||||
if let Some(file) = file_engine.read_file_to_string(&files[0]).await
|
||||
{
|
||||
log_entries.set(parse_log_file(&file));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
label {
|
||||
r#for: "files",
|
||||
class: "border w-full mb-2 bg-gray-200",
|
||||
style: "flex: 1; margin-left: 8px;",
|
||||
"Open log file"
|
||||
}
|
||||
}
|
||||
|
||||
// Column visibility checkboxes
|
||||
div { class: "mb-4",
|
||||
for (i, title) in column_titles.iter().enumerate() {
|
||||
label { class: "mr-4",
|
||||
input {
|
||||
r#type: "checkbox",
|
||||
checked: "{column_visibility()[i]}",
|
||||
onchange: move |_| {
|
||||
let mut visibility = column_visibility();
|
||||
visibility[i] = !visibility[i];
|
||||
column_visibility.set(visibility);
|
||||
}
|
||||
}
|
||||
" {title} "
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
class: "content",
|
||||
// Log entries table
|
||||
table { class: "table-auto w-full text-left",
|
||||
thead { class: "bg-gray-200",
|
||||
style: "position: sticky; top: 0;",
|
||||
tr {
|
||||
for (i, title) in column_titles.iter().enumerate() {
|
||||
if column_visibility()[i] {
|
||||
th {
|
||||
class: "px-4 py-2 relative",
|
||||
// Column title
|
||||
"{title}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tbody {
|
||||
for entry in log_entries().iter().filter(|entry| {
|
||||
entry.matches_query(&search_query())
|
||||
}) {
|
||||
tr { class: "hover:bg-gray-100",
|
||||
for i in 0..6 {
|
||||
if column_visibility()[i] {
|
||||
match i {
|
||||
0 => rsx! { td {
|
||||
class: "resize-null",
|
||||
style: "width: {column_widths[i]}px;min-width: {column_widths[i]}px;max-width: {column_widths[i]}px;",
|
||||
for (text, is_highlighted) in highlight_matches(&entry.timestamp, &highlight()) {
|
||||
if is_highlighted {
|
||||
span { class: "bg-yellow-200", "{text}" }
|
||||
} else {
|
||||
"{text}"
|
||||
}
|
||||
}
|
||||
} },
|
||||
1 => rsx! { td {
|
||||
class: "resize-null {entry.level_class()}",
|
||||
style: "width: {column_widths[i]}px;min-width: {column_widths[i]}px;max-width: {column_widths[i]}px;",
|
||||
for (text, is_highlighted) in highlight_matches(&entry.level.as_str(), &highlight()) {
|
||||
if is_highlighted {
|
||||
span { class: "bg-yellow-200", "{text}" }
|
||||
} else {
|
||||
"{text}"
|
||||
}
|
||||
}
|
||||
} },
|
||||
2 => rsx! { td {
|
||||
class: "resize-null",
|
||||
style: "width: {column_widths[i]}px;min-width: {column_widths[i]}px;max-width: {column_widths[i]}px;",
|
||||
for (text, is_highlighted) in highlight_matches(&entry.category, &highlight()) {
|
||||
if is_highlighted {
|
||||
span { class: "bg-yellow-200", "{text}" }
|
||||
} else {
|
||||
"{text}"
|
||||
}
|
||||
}
|
||||
} },
|
||||
3 => rsx! { td {
|
||||
class: "resize-null",
|
||||
style: "width: {column_widths[i]}px;min-width: {column_widths[i]}px;max-width: {column_widths[i]}px;",
|
||||
for (text, is_highlighted) in highlight_matches(&entry.thread, &highlight()) {
|
||||
if is_highlighted {
|
||||
span { class: "bg-yellow-200", "{text}" }
|
||||
} else {
|
||||
"{text}"
|
||||
}
|
||||
}
|
||||
} },
|
||||
4 => rsx! { td {
|
||||
for (text, is_highlighted) in highlight_matches(&entry.source, &highlight()) {
|
||||
if is_highlighted {
|
||||
span { class: "bg-yellow-200", "{text}" }
|
||||
} else {
|
||||
"{text}"
|
||||
}
|
||||
}
|
||||
} },
|
||||
5 => rsx! { td {
|
||||
for (text, is_highlighted) in highlight_matches(&entry.message, &highlight()) {
|
||||
if is_highlighted {
|
||||
span { class: "bg-yellow-200", "{text}" }
|
||||
} else {
|
||||
"{text}"
|
||||
}
|
||||
}
|
||||
} },
|
||||
_ => rsx!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
mode: "all",
|
||||
content: ["./src/**/*.{rs,html,css}", "./dist/**/*.html"],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
2024-10-03T09:51:03.821 Info General Thread[26308] sLib::Adhoc::AdhocSessionApplication@0x000001E024B52990
|
||||
Build date: 2024-09-30T08:36:04+00:00
|
||||
Build hash: e66c032c5
|
||||
Application path: C:\Users\SBIDER~1\AppData\Local\fastviewer\packages\adhoc_session\3.30.857\x64\AdhocSession.exe
|
||||
Application parameters: /session_id=0C45A839
|
||||
Application version: 3.30.857
|
||||
Process Id: 24592
|
||||
OS Version: 11 (10.0.26100)
|
||||
2024-10-03T09:51:03.825 Info General Thread[26308] sLib::Adhoc::AdhocSessionApplication@0x000001E024B52990 system language en-us
|
||||
2024-10-03T09:51:03.825 Info General Thread[26308] sLib::Adhoc::AdhocSessionApplication@0x000001E024B52990 using language en-us
|
||||
2024-10-03T09:51:03.841 Info General Thread[26308] sLib::Adhoc::AdhocSessionApplication@0x000001E024B52990 using FastViewer proxy config
|
||||
2024-10-03T09:51:03.841 Warning General Thread[26308] sLib::Adhoc::AdhocSessionApplication@0x000001E024B52990 using alpha rest api, rest-alpha.fastviewer.com
|
||||
2024-10-03T09:51:04.211 Info General Thread[27068] sLib::Remoted::DesktopSessionClientSessionImpl@0x000001E024B02760 Starting desktop process C:\Users\SBIDER~1\AppData\Local\fastviewer\packages\adhoc_session\3.30.857\x64\WebRCDesktopSession.exe /ipcserver_port=55577 /logging:file=info /logging:file:path=C:\Users\SBIDER~1\AppData\Local\fastviewer\apps\adhoc_session\webrc_desktop_2024-10-03T09-51-04_649a51e3-2614-462e-9050-f01cf1f79b25_0\desktopsession_649a51e3-2614-462e-9050-f01cf1f79b25_(pid).log /logging:short=true
|
||||
2024-10-03T09:51:06.987 Info General Thread[27836] sLib::WebRC::WebRCTerminalTunnelClient@0x000001E0279094E0 successfully started data source and connected, waiting for access
|
||||
2024-10-03T09:51:07.098 Info General Thread[27828] sLib::WebRC::WebRCTerminalTunnelClient@0x000001E0278FA740 successfully started data source and connected, waiting for access
|
||||
2024-10-03T09:51:11.294 Info General Thread[4488] sLib::WebRTC::sSingleTimedTransportConnector::Connection@0x000001E02797EE90 WebRTC connect finished. Upgrading transport.
|
||||
2024-10-03T09:51:11.372 Info General Thread[27836] sLib::Net::sLightweightUpgradeableTimedTransport@0x000001E026843F50 Upgraded transport
|
||||
2024-10-03T09:51:11.474 Info General Thread[27068] sLib::WebRTC::sSingleTimedTransportConnector::Connection@0x000001E027955420 WebRTC connect finished. Upgrading transport.
|
||||
2024-10-03T09:51:11.552 Info General Thread[27828] sLib::Net::sLightweightUpgradeableTimedTransport@0x000001E028EC8910 Upgraded transport
|
||||
2024-10-03T09:51:24.602 Error General Thread[4488] sLib::Net::sLightweightTimeSyncingTransport@0x000001E028EF40C0 request_id=2884121645 Read error Internal error: Underlying connection closed (-75) sLib::WebRTC::sDataChannel::tryEndReadOperation
|
||||
File: C:\GitLab-Runner\builds\i385pLWF\0\colyoo\colyoo\source\Multimedia\sLibWebRTC\sWebRTCDataChannel.cpp:337
|
||||
2024-10-03T09:51:24.612 Error General Thread[4488] sLib::Net::sLightweightTimeSyncingTransport@0x000001E028EF3760 request_id=2884121636 Read error Internal error: Underlying connection closed (-75) sLib::WebRTC::sDataChannel::tryEndReadOperation
|
||||
File: C:\GitLab-Runner\builds\i385pLWF\0\colyoo\colyoo\source\Multimedia\sLibWebRTC\sWebRTCDataChannel.cpp:337
|
||||
2024-10-03T09:51:24.628 Info General Thread[4488] sLib::WebRC::WebRCTerminalTunnelClient@0x000001E0279094E0 access cancelled => terminating
|
||||
2024-10-03T09:51:24.630 Info General Thread[4488] sLib::Adhoc::AdhocSSHSessionManager@0x000001E026833930 SESSION ENDED ssh 3ac5f50c-9a65-4790-b739-673e7a8b0376 Internal error: Underlying connection closed (-75) sLib::WebRTC::sDataChannel::tryEndReadOperation
|
||||
File: C:\GitLab-Runner\builds\i385pLWF\0\colyoo\colyoo\source\Multimedia\sLibWebRTC\sWebRTCDataChannel.cpp:337
|
||||
2024-10-03T09:51:24.630 Info General Thread[27068] sLib::WebRC::WebRCTerminalTunnelClient@0x000001E0278FA740 access cancelled => terminating
|
||||
2024-10-03T09:51:24.630 Info General Thread[27068] sLib::Adhoc::AdhocSSHSessionManager@0x000001E026822470 SESSION ENDED ssh 1b1a6d23-ab73-450f-b0c5-5fd707cbf243 Internal error: Underlying connection closed (-75) sLib::WebRTC::sDataChannel::tryEndReadOperation
|
||||
File: C:\GitLab-Runner\builds\i385pLWF\0\colyoo\colyoo\source\Multimedia\sLibWebRTC\sWebRTCDataChannel.cpp:337
|
||||
2024-10-03T09:51:24.640 Warning Remoted Thread[24772] sLib::WebRC::WebRCDesktopSession@0x000001E0267A7B50 Failed to set OS session ID 1 An existing connection was forcibly closed by the remote host
|
||||
2024-10-03T09:51:24.640 Info General Thread[4488] sLib::Adhoc::DesktopSessionManager@0x000001E02681B7B0 SESSION ENDED desktop 649a51e3-2614-462e-9050-f01cf1f79b25 Internal error: Connection closed locally (-69) sLib::WebRC::WebRCDesktopSession::performStart::<lambda_2>::()::<lambda_2>::operator ()
|
||||
File: C:\GitLab-Runner\builds\i385pLWF\0\colyoo\colyoo\source\WebRC\WebRCConnectionServiceLib\WebRCDesktopSession.cpp:162
|
||||
Loading…
Reference in New Issue