Initial commit — Work Journal project (prototype, Android app, backups, project log)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"cssTheme": "Obuntu",
|
||||
"accentColor": "#579bb2",
|
||||
"theme": "obsidian"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
[
|
||||
"highlightr-plugin",
|
||||
"pexels-banner"
|
||||
]
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"file-explorer": true,
|
||||
"global-search": true,
|
||||
"switcher": true,
|
||||
"graph": true,
|
||||
"backlink": true,
|
||||
"canvas": true,
|
||||
"outgoing-link": true,
|
||||
"tag-pane": true,
|
||||
"footnotes": false,
|
||||
"properties": true,
|
||||
"page-preview": true,
|
||||
"daily-notes": true,
|
||||
"templates": true,
|
||||
"note-composer": true,
|
||||
"command-palette": true,
|
||||
"slash-command": false,
|
||||
"editor-status": true,
|
||||
"bookmarks": true,
|
||||
"markdown-importer": false,
|
||||
"zk-prefixer": false,
|
||||
"random-note": false,
|
||||
"outline": true,
|
||||
"word-count": true,
|
||||
"slides": false,
|
||||
"audio-recorder": false,
|
||||
"workspaces": false,
|
||||
"file-recovery": true,
|
||||
"publish": false,
|
||||
"sync": true,
|
||||
"bases": true,
|
||||
"webviewer": false
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"highlighterStyle": "realistic",
|
||||
"highlighterMethods": "inline-styles",
|
||||
"highlighters": {
|
||||
"Pink": "#FFB8EBA6",
|
||||
"Red": "#FF5582A6",
|
||||
"Orange": "#FFB86CA6",
|
||||
"Yellow": "#FFF3A3A6",
|
||||
"Green": "#BBFABBA6",
|
||||
"Cyan": "#ABF7F7A6",
|
||||
"Blue": "#ADCCFFA6",
|
||||
"Purple": "#D2B3FFA6",
|
||||
"Grey": "#CACFD9A6"
|
||||
},
|
||||
"highlighterOrder": [
|
||||
"Pink",
|
||||
"Red",
|
||||
"Orange",
|
||||
"Yellow",
|
||||
"Green",
|
||||
"Cyan",
|
||||
"Blue",
|
||||
"Purple",
|
||||
"Grey"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"id": "highlightr-plugin",
|
||||
"name": "Highlightr",
|
||||
"version": "1.2.2",
|
||||
"minAppVersion": "0.12.8",
|
||||
"description": "A minimal and aesthetically pleasing highlighting menu that makes color-coded highlighting much easier with a configurable assortment of highlight colors 🎨.",
|
||||
"author": "chetachi",
|
||||
"authorUrl": "https://github.com/chetachiezikeuzor",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
@@ -0,0 +1,774 @@
|
||||
/*highlighter style*/
|
||||
/*lowlight*/
|
||||
.highlightr-lowlight mark,
|
||||
.highlightr-lowlight span.cm-highlight,
|
||||
.highlightr-lowlight .markdown-preview-view mark {
|
||||
--lowlight-background: var(--background-primary);
|
||||
border-radius: 0;
|
||||
background-image: linear-gradient(
|
||||
360deg,
|
||||
rgba(255, 255, 255, 0) 40%,
|
||||
var(--lowlight-background) 40%
|
||||
) !important;
|
||||
}
|
||||
|
||||
.highlightr-lowlight .workspace-split.mod-left-split mark,
|
||||
.highlightr-lowlight .workspace-split.mod-left-split span.cm-highlight,
|
||||
.highlightr-lowlight
|
||||
.workspace-split.mod-left-split
|
||||
.markdown-preview-view
|
||||
mark,
|
||||
.highlightr-lowlight .workspace-split.mod-right-split mark,
|
||||
.highlightr-lowlight .workspace-split.mod-right-split span.cm-highlight,
|
||||
.highlightr-lowlight
|
||||
.workspace-split.mod-right-split
|
||||
.markdown-preview-view
|
||||
mark {
|
||||
--lowlight-background: var(--background-secondary);
|
||||
}
|
||||
|
||||
.highlightr-lowlight .admonition-content mark,
|
||||
.highlightr-lowlight .admonition-content span.cm-highlight,
|
||||
.highlightr-lowlight .admonition-content > .markdown-preview-view mark {
|
||||
--lowlight-background: var(--background-primary-alt);
|
||||
}
|
||||
|
||||
/*floating*/
|
||||
.highlightr-floating mark,
|
||||
.highlightr-floating span.cm-highlight,
|
||||
.highlightr-floating .markdown-preview-view mark {
|
||||
--floating-background: var(--background-primary);
|
||||
border-radius: 0;
|
||||
padding-bottom: 5px;
|
||||
background-image: linear-gradient(
|
||||
360deg,
|
||||
rgba(255, 255, 255, 0) 28%,
|
||||
var(--floating-background) 28%
|
||||
) !important;
|
||||
}
|
||||
|
||||
.highlightr-floating .workspace-split.mod-left-split mark,
|
||||
.highlightr-floating .workspace-split.mod-left-split span.cm-highlight,
|
||||
.highlightr-floating
|
||||
.workspace-split.mod-left-split
|
||||
.markdown-preview-view
|
||||
mark,
|
||||
.highlightr-floating .workspace-split.mod-right-split mark,
|
||||
.highlightr-floating .workspace-split.mod-right-split span.cm-highlight,
|
||||
.highlightr-floating
|
||||
.workspace-split.mod-right-split
|
||||
.markdown-preview-view
|
||||
mark {
|
||||
--floating-background: var(--background-secondary);
|
||||
}
|
||||
|
||||
.highlightr-floating .admonition-content mark,
|
||||
.highlightr-floating .admonition-content span.cm-highlight,
|
||||
.highlightr-floating .admonition-content > .markdown-preview-view mark {
|
||||
--floating-background: var(--background-primary-alt);
|
||||
}
|
||||
|
||||
/*rounded*/
|
||||
.highlightr-rounded mark,
|
||||
.highlightr-rounded .markdown-preview-view mark {
|
||||
margin: 0 -0.05em;
|
||||
padding: 0.125em 0.15em;
|
||||
border-radius: 0.2em;
|
||||
-webkit-box-decoration-break: clone;
|
||||
box-decoration-break: clone;
|
||||
}
|
||||
|
||||
.highlightr-rounded span.cm-highlight {
|
||||
border-radius: 0.2em;
|
||||
-webkit-box-decoration-break: clone;
|
||||
box-decoration-break: clone;
|
||||
}
|
||||
|
||||
.highlightr-rounded .cm-s-obsidian span.cm-highlight {
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
.highlightr-rounded .cm-highlight + span.cm-formatting-highlight {
|
||||
padding-left: 0em;
|
||||
padding-right: 0.15em;
|
||||
-webkit-box-decoration-break: clone;
|
||||
box-decoration-break: clone;
|
||||
}
|
||||
|
||||
/*realistic*/
|
||||
.highlightr-realistic mark,
|
||||
.highlightr-realistic .markdown-preview-view mark {
|
||||
margin: 0 -0.05em;
|
||||
padding: 0.1em 0.4em;
|
||||
border-radius: 0.8em 0.3em;
|
||||
-webkit-box-decoration-break: clone;
|
||||
box-decoration-break: clone;
|
||||
text-shadow: 0 0 0.75em var(--background-primary-alt);
|
||||
}
|
||||
|
||||
.highlightr-realistic.hide-tokens .cm-s-obsidian span.cm-highlight,
|
||||
.hide-tokens.highlightr-realistic .cm-s-obsidian span.cm-highlight {
|
||||
border-radius: 0.8em 0.3em;
|
||||
}
|
||||
|
||||
.highlightr-realistic .cm-s-obsidian span.cm-highlight {
|
||||
padding: 0.15em 0.25em;
|
||||
-webkit-box-decoration-break: clone;
|
||||
box-decoration-break: clone;
|
||||
text-shadow: 0 0 0.75em var(--background-primary-alt);
|
||||
}
|
||||
|
||||
.highlightr-realistic .cm-s-obsidian span.cm-formatting-highlight {
|
||||
margin: 0 0 0 -0.05em;
|
||||
padding: 0.15em 0.25em;
|
||||
border-radius: 0.8em 0 0 0.3em;
|
||||
-webkit-box-decoration-break: clone;
|
||||
box-decoration-break: clone;
|
||||
}
|
||||
|
||||
.highlightr-realistic
|
||||
.cm-s-obsidian
|
||||
.cm-highlight
|
||||
+ span.cm-formatting-highlight {
|
||||
margin: 0 -0.05em 0 0;
|
||||
padding: 0.15em 0.25em;
|
||||
border-radius: 0 0.3em 0.8em 0;
|
||||
-webkit-box-decoration-break: clone;
|
||||
box-decoration-break: clone;
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
button.copy-highlights {
|
||||
padding: 4px 14px;
|
||||
border-radius: 5px;
|
||||
background-color: var(--interactive-accent);
|
||||
}
|
||||
|
||||
.copy-highlights svg {
|
||||
width: 1.3em;
|
||||
height: 1.3em;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
details summary.highlight-summary:before {
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
content: "☐";
|
||||
font-size: 9px;
|
||||
cursor: pointer;
|
||||
margin-right: 5px;
|
||||
display: inline-block;
|
||||
vertical-align: 0.05em;
|
||||
background-color: currentColor;
|
||||
-webkit-mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="black" d="M10.707 17.707L16.414 12l-5.707-5.707l-1.414 1.414L13.586 12l-4.293 4.293z"></path></svg>');
|
||||
}
|
||||
|
||||
details[open] summary.highlight-summary::before {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
/*highlightr component*/
|
||||
|
||||
@keyframes fade {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
opacity: 0.9;
|
||||
}
|
||||
40% {
|
||||
opacity: 0.95;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.menu.highlighterContainer {
|
||||
min-width: 140px;
|
||||
max-width: 225px;
|
||||
max-height: 180px;
|
||||
padding-left: 0em;
|
||||
padding: 0;
|
||||
margin: 0 auto;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
position: fixed;
|
||||
animation: fade 300ms ease-in-out;
|
||||
background-color: var(--background-primary);
|
||||
box-shadow: 0px 3px 25px rgba(31, 38, 135, 0.1);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
.menu.highlighterContainer .menu-item .menu-item-icon {
|
||||
display: inline-block;
|
||||
width: 25px;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.menu.highlighterContainer .menu-item {
|
||||
display: flex;
|
||||
padding: 2px 14px 3px 14px;
|
||||
align-items: unset;
|
||||
margin: auto;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
height: 32px;
|
||||
line-height: 31px;
|
||||
white-space: nowrap;
|
||||
border-radius: 0;
|
||||
border-bottom: 1px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
.menu.highlighterContainer .menu-item:last-of-type {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
SETTINGS TAB
|
||||
----------------------------------------------------------------*/
|
||||
|
||||
button.HighlightrSettingsButton {
|
||||
padding: 4px 14px;
|
||||
border-radius: 6px;
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
button.HighlightrSettingsButton svg {
|
||||
width: 1.3em;
|
||||
height: 1.3em;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.highlighter-settings-color,
|
||||
.highlighter-settings-value {
|
||||
width: 42%;
|
||||
color: var(--text-normal);
|
||||
}
|
||||
|
||||
.highlighterplugin-setting-item {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.highlighterplugin-setting-item .setting-item-control {
|
||||
justify-content: space-between;
|
||||
margin-top: 12px;
|
||||
align-content: center;
|
||||
align-items: flex-end;
|
||||
grid-gap: 6px;
|
||||
}
|
||||
|
||||
.modal.mod-settings
|
||||
button:not(.mod-cta):not(.mod-warning).HighlightrSettingsButton.HighlightrSettingsButtonAdd,
|
||||
button:not(.mod-cta):not(.mod-warning).HighlightrSettingsButton.HighlightrSettingsButtonAdd {
|
||||
background-color: var(--interactive-accent);
|
||||
}
|
||||
|
||||
.modal.mod-settings
|
||||
button:not(.mod-cta):not(.mod-warning).HighlightrSettingsButton.HighlightrSettingsButtonDelete,
|
||||
button:not(.mod-cta):not(.mod-warning).HighlightrSettingsButton.HighlightrSettingsButtonDelete {
|
||||
background-color: #989cab;
|
||||
}
|
||||
|
||||
/**/
|
||||
.highlighter-setting-icon {
|
||||
display: flex;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.highlighter-item-draggable {
|
||||
cursor: grab;
|
||||
display: grid;
|
||||
grid-gap: 8px;
|
||||
grid-template-columns: 0.5fr 7fr;
|
||||
align-items: center;
|
||||
border-top: 1px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
.HighlightrSettingsTabsContainer {
|
||||
border-bottom: 1px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
.setting-item.highlighter-setting-item:first-child {
|
||||
padding-top: 18px;
|
||||
}
|
||||
|
||||
.highlighter-setting-item {
|
||||
padding: 18px 0 18px 0;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.highlighter-sortable-fallback {
|
||||
cursor: grabbing;
|
||||
box-shadow: 0px 3px 32px rgb(31 38 135 / 15%);
|
||||
}
|
||||
|
||||
.highlighter-sortable-grab {
|
||||
cursor: grabbing !important;
|
||||
}
|
||||
|
||||
.highlighter-sortable-ghost {
|
||||
opacity: 0.4;
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.highlighter-sortable-chosen {
|
||||
cursor: grabbing;
|
||||
padding: 0 0 0 18px;
|
||||
background-color: var(--background-primary);
|
||||
}
|
||||
|
||||
.highlighter-sortable-drag {
|
||||
cursor: grabbing;
|
||||
box-shadow: 0px 3px 32px rgb(31 38 135 / 15%);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
HIGHLIGHTR SUPPORT
|
||||
----------------------------------------------------------------*/
|
||||
|
||||
.hltrDonationSection {
|
||||
width: 65%;
|
||||
height: 50vh;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
color: var(--text-normal);
|
||||
}
|
||||
|
||||
.pcr-app .pcr-swatches > button {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.pickr .pcr-button {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.themed-color-wrapper > div {
|
||||
background: var(--background-primary);
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.themed-color-wrapper > div + div {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.themed-color-wrapper button {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.themed-color-wrapper .pickr-reset > button {
|
||||
margin: 0 0 0 10px;
|
||||
padding: 9px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.themed-color-wrapper .pickr-reset > button > svg {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
PICKR 1.8.2 MIT | https://github.com/Simonwep/pickr
|
||||
----------------------------------------------------------------*/
|
||||
.pickr {
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
transform: translateY(0);
|
||||
}
|
||||
.pickr * {
|
||||
box-sizing: border-box;
|
||||
outline: none;
|
||||
border: none;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
.pickr .pcr-button {
|
||||
position: relative;
|
||||
height: 2em;
|
||||
width: 2em;
|
||||
padding: 0.5em;
|
||||
cursor: pointer;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
|
||||
"Helvetica Neue", Arial, sans-serif;
|
||||
border-radius: 0.15em;
|
||||
background: url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" stroke="%2342445A" stroke-width="5px" stroke-linecap="round"><path d="M45,45L5,5"></path><path d="M45,5L5,45"></path></svg>')
|
||||
no-repeat center;
|
||||
background-size: 0;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.pickr .pcr-button::before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="white" d="M1,0H2V1H1V0ZM0,1H1V2H0V1Z"/><path fill="gray" d="M0,0H1V1H0V0ZM1,1H2V2H1V1Z"/></svg>');
|
||||
background-size: 0.5em;
|
||||
border-radius: 0.15em;
|
||||
z-index: -1;
|
||||
}
|
||||
.pickr .pcr-button::before {
|
||||
z-index: initial;
|
||||
}
|
||||
.pickr .pcr-button::after {
|
||||
position: absolute;
|
||||
content: "";
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
transition: background 0.3s;
|
||||
background: var(--pcr-color);
|
||||
border-radius: 0.15em;
|
||||
}
|
||||
.pickr .pcr-button.clear {
|
||||
background-size: 70%;
|
||||
}
|
||||
.pickr .pcr-button.clear::before {
|
||||
opacity: 0;
|
||||
}
|
||||
.pickr .pcr-button.clear:focus {
|
||||
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.85), 0 0 0 3px var(--pcr-color);
|
||||
}
|
||||
.pickr .pcr-button.disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.pickr *,
|
||||
.pcr-app * {
|
||||
box-sizing: border-box;
|
||||
outline: none;
|
||||
border: none;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
.pickr input:focus,
|
||||
.pickr input.pcr-active,
|
||||
.pickr button:focus,
|
||||
.pickr button.pcr-active,
|
||||
.pcr-app input:focus,
|
||||
.pcr-app input.pcr-active,
|
||||
.pcr-app button:focus,
|
||||
.pcr-app button.pcr-active {
|
||||
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.85), 0 0 0 3px var(--pcr-color);
|
||||
}
|
||||
.pickr .pcr-palette,
|
||||
.pickr .pcr-slider,
|
||||
.pcr-app .pcr-palette,
|
||||
.pcr-app .pcr-slider {
|
||||
transition: box-shadow 0.3s;
|
||||
}
|
||||
.pickr .pcr-palette:focus,
|
||||
.pickr .pcr-slider:focus,
|
||||
.pcr-app .pcr-palette:focus,
|
||||
.pcr-app .pcr-slider:focus {
|
||||
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.85), 0 0 0 3px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.pcr-app {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 10000;
|
||||
border-radius: 0.1em;
|
||||
background: #fff;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity 0.3s, visibility 0s 0.3s;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
|
||||
"Helvetica Neue", Arial, sans-serif;
|
||||
box-shadow: 0 0.15em 1.5em 0 rgba(0, 0, 0, 0.1), 0 0 1em 0 rgba(0, 0, 0, 0.03);
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.pcr-app.visible {
|
||||
transition: opacity 0.3s;
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
.pcr-app .pcr-swatches {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 0.75em;
|
||||
}
|
||||
.pcr-app .pcr-swatches.pcr-last {
|
||||
margin: 0;
|
||||
}
|
||||
@supports (display: grid) {
|
||||
.pcr-app .pcr-swatches {
|
||||
display: grid;
|
||||
align-items: center;
|
||||
grid-template-columns: repeat(auto-fit, 1.75em);
|
||||
}
|
||||
}
|
||||
.pcr-app .pcr-swatches > button {
|
||||
font-size: 1em;
|
||||
position: relative;
|
||||
width: calc(1.75em - 5px);
|
||||
height: calc(1.75em - 5px);
|
||||
border-radius: 0.15em;
|
||||
cursor: pointer;
|
||||
margin: 2.5px;
|
||||
flex-shrink: 0;
|
||||
justify-self: center;
|
||||
transition: all 0.15s;
|
||||
overflow: hidden;
|
||||
background: transparent;
|
||||
z-index: 1;
|
||||
}
|
||||
.pcr-app .pcr-swatches > button::before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="white" d="M1,0H2V1H1V0ZM0,1H1V2H0V1Z"/><path fill="gray" d="M0,0H1V1H0V0ZM1,1H2V2H1V1Z"/></svg>');
|
||||
background-size: 6px;
|
||||
border-radius: 0.15em;
|
||||
z-index: -1;
|
||||
}
|
||||
.pcr-app .pcr-swatches > button::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--pcr-color);
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
border-radius: 0.15em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.pcr-app .pcr-swatches > button:hover {
|
||||
filter: brightness(1.05);
|
||||
}
|
||||
.pcr-app .pcr-swatches > button:not(.pcr-active) {
|
||||
box-shadow: none;
|
||||
}
|
||||
.pcr-app .pcr-interaction {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
margin: 0 -0.2em 0 -0.2em;
|
||||
}
|
||||
.pcr-app .pcr-interaction > * {
|
||||
margin: 0 0.2em;
|
||||
}
|
||||
.pcr-app .pcr-interaction input {
|
||||
letter-spacing: 0.07em;
|
||||
font-size: 0.75em;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
color: #75797e;
|
||||
background: #f1f3f4;
|
||||
border-radius: 0.15em;
|
||||
transition: all 0.15s;
|
||||
padding: 0.45em 0.5em;
|
||||
margin-top: 0.75em;
|
||||
}
|
||||
.pcr-app .pcr-interaction input:hover {
|
||||
filter: brightness(0.975);
|
||||
}
|
||||
.pcr-app .pcr-interaction input:focus {
|
||||
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.85),
|
||||
0 0 0 3px rgba(66, 133, 244, 0.75);
|
||||
}
|
||||
.pcr-app .pcr-interaction .pcr-result {
|
||||
color: #75797e;
|
||||
text-align: left;
|
||||
flex: 1 1 8em;
|
||||
min-width: 8em;
|
||||
transition: all 0.2s;
|
||||
border-radius: 0.15em;
|
||||
background: #f1f3f4;
|
||||
cursor: text;
|
||||
}
|
||||
.pcr-app .pcr-interaction .pcr-result::-moz-selection {
|
||||
background: #4285f4;
|
||||
color: #fff;
|
||||
}
|
||||
.pcr-app .pcr-interaction .pcr-result::selection {
|
||||
background: #4285f4;
|
||||
color: #fff;
|
||||
}
|
||||
.pcr-app .pcr-interaction .pcr-type.active {
|
||||
color: #fff;
|
||||
background: #4285f4;
|
||||
}
|
||||
.pcr-app .pcr-interaction .pcr-save,
|
||||
.pcr-app .pcr-interaction .pcr-cancel,
|
||||
.pcr-app .pcr-interaction .pcr-clear {
|
||||
color: #fff;
|
||||
width: auto;
|
||||
}
|
||||
.pcr-app .pcr-interaction .pcr-save,
|
||||
.pcr-app .pcr-interaction .pcr-cancel,
|
||||
.pcr-app .pcr-interaction .pcr-clear {
|
||||
color: #fff;
|
||||
}
|
||||
.pcr-app .pcr-interaction .pcr-save:hover,
|
||||
.pcr-app .pcr-interaction .pcr-cancel:hover,
|
||||
.pcr-app .pcr-interaction .pcr-clear:hover {
|
||||
filter: brightness(0.925);
|
||||
}
|
||||
.pcr-app .pcr-interaction .pcr-save {
|
||||
background: #4285f4;
|
||||
}
|
||||
.pcr-app .pcr-interaction .pcr-clear,
|
||||
.pcr-app .pcr-interaction .pcr-cancel {
|
||||
background: #f44250;
|
||||
}
|
||||
.pcr-app .pcr-interaction .pcr-clear:focus,
|
||||
.pcr-app .pcr-interaction .pcr-cancel:focus {
|
||||
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.85),
|
||||
0 0 0 3px rgba(244, 66, 80, 0.75);
|
||||
}
|
||||
.pcr-app .pcr-selection .pcr-picker {
|
||||
position: absolute;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
border: 2px solid #fff;
|
||||
border-radius: 100%;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.pcr-app .pcr-selection .pcr-color-palette,
|
||||
.pcr-app .pcr-selection .pcr-color-chooser,
|
||||
.pcr-app .pcr-selection .pcr-color-opacity {
|
||||
position: relative;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
cursor: grab;
|
||||
cursor: -webkit-grab;
|
||||
}
|
||||
.pcr-app .pcr-selection .pcr-color-palette:active,
|
||||
.pcr-app .pcr-selection .pcr-color-chooser:active,
|
||||
.pcr-app .pcr-selection .pcr-color-opacity:active {
|
||||
cursor: grabbing;
|
||||
cursor: -webkit-grabbing;
|
||||
}
|
||||
.pcr-app[data-theme="nano"] {
|
||||
width: 14.25em;
|
||||
max-width: 95vw;
|
||||
}
|
||||
.pcr-app[data-theme="nano"] .pcr-swatches {
|
||||
margin-top: 0.6em;
|
||||
padding: 0 0.6em;
|
||||
}
|
||||
.pcr-app[data-theme="nano"] .pcr-interaction {
|
||||
padding: 0 0.6em 0.6em 0.6em;
|
||||
}
|
||||
.pcr-app[data-theme="nano"] .pcr-selection {
|
||||
display: grid;
|
||||
grid-gap: 0.6em;
|
||||
grid-template-columns: 1fr 4fr;
|
||||
grid-template-rows: 5fr auto auto;
|
||||
align-items: center;
|
||||
height: 10.5em;
|
||||
width: 100%;
|
||||
align-self: flex-start;
|
||||
}
|
||||
.pcr-app[data-theme="nano"] .pcr-selection .pcr-color-preview {
|
||||
grid-area: 2 / 1 / 4 / 1;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
margin-left: 0.6em;
|
||||
}
|
||||
.pcr-app[data-theme="nano"] .pcr-selection .pcr-color-preview .pcr-last-color {
|
||||
display: none;
|
||||
}
|
||||
.pcr-app[data-theme="nano"]
|
||||
.pcr-selection
|
||||
.pcr-color-preview
|
||||
.pcr-current-color {
|
||||
position: relative;
|
||||
background: var(--pcr-color);
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
border-radius: 50em;
|
||||
overflow: hidden;
|
||||
}
|
||||
.pcr-app[data-theme="nano"]
|
||||
.pcr-selection
|
||||
.pcr-color-preview
|
||||
.pcr-current-color::before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="white" d="M1,0H2V1H1V0ZM0,1H1V2H0V1Z"/><path fill="gray" d="M0,0H1V1H0V0ZM1,1H2V2H1V1Z"/></svg>');
|
||||
background-size: 0.5em;
|
||||
border-radius: 0.15em;
|
||||
z-index: -1;
|
||||
}
|
||||
.pcr-app[data-theme="nano"] .pcr-selection .pcr-color-palette {
|
||||
grid-area: 1 / 1 / 2 / 3;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
.pcr-app[data-theme="nano"] .pcr-selection .pcr-color-palette .pcr-palette {
|
||||
border-radius: 0.15em;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.pcr-app[data-theme="nano"]
|
||||
.pcr-selection
|
||||
.pcr-color-palette
|
||||
.pcr-palette::before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="white" d="M1,0H2V1H1V0ZM0,1H1V2H0V1Z"/><path fill="gray" d="M0,0H1V1H0V0ZM1,1H2V2H1V1Z"/></svg>');
|
||||
background-size: 0.5em;
|
||||
border-radius: 0.15em;
|
||||
z-index: -1;
|
||||
}
|
||||
.pcr-app[data-theme="nano"] .pcr-selection .pcr-color-chooser {
|
||||
grid-area: 2 / 2 / 2 / 2;
|
||||
}
|
||||
.pcr-app[data-theme="nano"] .pcr-selection .pcr-color-opacity {
|
||||
grid-area: 3 / 2 / 3 / 2;
|
||||
}
|
||||
.pcr-app[data-theme="nano"] .pcr-selection .pcr-color-chooser,
|
||||
.pcr-app[data-theme="nano"] .pcr-selection .pcr-color-opacity {
|
||||
height: 0.5em;
|
||||
margin: 0 0.6em;
|
||||
}
|
||||
.pcr-app[data-theme="nano"] .pcr-selection .pcr-color-chooser .pcr-picker,
|
||||
.pcr-app[data-theme="nano"] .pcr-selection .pcr-color-opacity .pcr-picker {
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.pcr-app[data-theme="nano"] .pcr-selection .pcr-color-chooser .pcr-slider,
|
||||
.pcr-app[data-theme="nano"] .pcr-selection .pcr-color-opacity .pcr-slider {
|
||||
flex-grow: 1;
|
||||
border-radius: 50em;
|
||||
}
|
||||
.pcr-app[data-theme="nano"] .pcr-selection .pcr-color-chooser .pcr-slider {
|
||||
background: linear-gradient(to right, red, #ff0, lime, cyan, blue, #f0f, red);
|
||||
}
|
||||
.pcr-app[data-theme="nano"] .pcr-selection .pcr-color-opacity .pcr-slider {
|
||||
background: linear-gradient(to right, transparent, black),
|
||||
url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="white" d="M1,0H2V1H1V0ZM0,1H1V2H0V1Z"/><path fill="gray" d="M0,0H1V1H0V0ZM1,1H2V2H1V1Z"/></svg>');
|
||||
background-size: 100%, 0.25em;
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
{
|
||||
"pixelBannerPlusEmail": "",
|
||||
"pixelBannerPlusApiKey": "",
|
||||
"pixelBannerPlusEnabled": true,
|
||||
"apiProvider": "all",
|
||||
"pexelsApiKey": "",
|
||||
"pixabayApiKey": "",
|
||||
"flickrApiKey": "",
|
||||
"unsplashApiKey": "",
|
||||
"imageSize": "medium",
|
||||
"imageOrientation": "landscape",
|
||||
"numberOfImages": 10,
|
||||
"defaultKeywords": "nature, abstract, landscape, technology, art, cityscape, wildlife, ocean, mountains, forest, space, architecture, food, travel, science, music, sports, fashion, business, education, health, culture, history, weather, transportation, industry, people, animals, plants, patterns",
|
||||
"xPosition": 50,
|
||||
"yPosition": 60,
|
||||
"customBannerField": [
|
||||
"banner"
|
||||
],
|
||||
"customXPositionField": [
|
||||
"banner-x",
|
||||
"x"
|
||||
],
|
||||
"customYPositionField": [
|
||||
"banner-y",
|
||||
"y"
|
||||
],
|
||||
"customContentStartField": [
|
||||
"content-start"
|
||||
],
|
||||
"customImageDisplayField": [
|
||||
"banner-display"
|
||||
],
|
||||
"customImageRepeatField": [
|
||||
"banner-repeat"
|
||||
],
|
||||
"customBannerMaxWidthField": [
|
||||
"banner-max-width"
|
||||
],
|
||||
"customBannerAlignmentField": [
|
||||
"banner-align"
|
||||
],
|
||||
"customBannerHeightField": [
|
||||
"banner-height"
|
||||
],
|
||||
"customFadeField": [
|
||||
"banner-fade"
|
||||
],
|
||||
"customBorderRadiusField": [
|
||||
"banner-radius"
|
||||
],
|
||||
"customTitleColorField": [
|
||||
"banner-inline-title-color"
|
||||
],
|
||||
"customBannerShuffleField": [
|
||||
"banner-shuffle"
|
||||
],
|
||||
"customBannerIconField": [
|
||||
"icon"
|
||||
],
|
||||
"customBannerIconImageField": [
|
||||
"icon-image"
|
||||
],
|
||||
"customBannerIconSizeField": [
|
||||
"icon-size"
|
||||
],
|
||||
"customBannerIconImageSizeMultiplierField": [
|
||||
"icon-image-size-multiplier"
|
||||
],
|
||||
"customBannerIconTextVerticalOffsetField": [
|
||||
"icon-text-vertical-offset"
|
||||
],
|
||||
"customBannerIconRotateField": [
|
||||
"icon-rotate"
|
||||
],
|
||||
"customBannerIconXPositionField": [
|
||||
"icon-x"
|
||||
],
|
||||
"customBannerIconOpacityField": [
|
||||
"icon-opacity"
|
||||
],
|
||||
"customBannerIconColorField": [
|
||||
"icon-color"
|
||||
],
|
||||
"customBannerIconFontWeightField": [
|
||||
"icon-font-weight"
|
||||
],
|
||||
"customBannerIconBackgroundColorField": [
|
||||
"icon-bg-color"
|
||||
],
|
||||
"customBannerIconPaddingXField": [
|
||||
"icon-padding-x"
|
||||
],
|
||||
"customBannerIconPaddingYField": [
|
||||
"icon-padding-y"
|
||||
],
|
||||
"customBannerIconBorderRadiusField": [
|
||||
"icon-border-radius"
|
||||
],
|
||||
"customBannerIconVerticalOffsetField": [
|
||||
"icon-y"
|
||||
],
|
||||
"customBannerIconImageAlignmentField": [
|
||||
"banner-icon-image-alignment"
|
||||
],
|
||||
"customFlagColorField": [
|
||||
"pixel-banner-flag-color"
|
||||
],
|
||||
"folderImages": [],
|
||||
"contentStartPosition": 355,
|
||||
"imageDisplay": "cover",
|
||||
"imageRepeat": false,
|
||||
"bannerHeight": 350,
|
||||
"bannerMaxWidth": 2560,
|
||||
"fade": -65,
|
||||
"bannerFadeInAnimationDuration": 354,
|
||||
"borderRadius": 0,
|
||||
"showPinIcon": false,
|
||||
"pinnedImageFolder": "pixel-banner-images",
|
||||
"pinnedImageFilename": "pixel-banner-image",
|
||||
"imagePropertyFormat": "image",
|
||||
"showReleaseNotes": true,
|
||||
"lastVersion": "3.6.18",
|
||||
"showRefreshIcon": false,
|
||||
"showViewImageIcon": false,
|
||||
"hidePixelBannerFields": true,
|
||||
"hidePropertiesSectionIfOnlyBanner": true,
|
||||
"titleColor": "var(--inline-title-color)",
|
||||
"enableImageShuffle": false,
|
||||
"hideEmbeddedNoteTitles": false,
|
||||
"hideEmbeddedNoteBanners": false,
|
||||
"showBannerInPopoverPreviews": true,
|
||||
"showSelectImageIcon": true,
|
||||
"selectImageIconOpacity": 40,
|
||||
"selectImageIconFlag": "red-fade-dark",
|
||||
"defaultSelectImagePath": "",
|
||||
"defaultSelectIconPath": "",
|
||||
"useShortPath": true,
|
||||
"bannerGap": 0,
|
||||
"bannerIconSize": 70,
|
||||
"bannerIconImageSizeMultiplier": 1,
|
||||
"bannerIconTextVerticalOffset": 0,
|
||||
"bannerIconXPosition": 75,
|
||||
"bannerIconOpacity": 100,
|
||||
"bannerIconColor": "",
|
||||
"bannerIconFontWeight": "normal",
|
||||
"bannerIconBackgroundColor": "",
|
||||
"bannerIconPaddingX": "10",
|
||||
"bannerIconPaddingY": "10",
|
||||
"bannerIconBorderRadius": "17",
|
||||
"bannerIconVerticalOffset": "0",
|
||||
"bannerIconImageAlignment": "left",
|
||||
"openTargetingModalAfterSelectingBannerOrIcon": true,
|
||||
"enableDailyGame": false
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"id": "pexels-banner",
|
||||
"name": "Pixel Banner",
|
||||
"version": "3.6.18",
|
||||
"minAppVersion": "1.6.0",
|
||||
"description": "Enhance your notes with customizable banner images, including AI-generated designs and a curated store of downloadable banners. Transform your workspace with visually stunning headers that add context, improve aesthetics, and take your note-taking beyond the ordinary.",
|
||||
"author": "Justin Parker (eQui\\\\ Labs)",
|
||||
"authorUrl": "https://www.equilllabs.com",
|
||||
"fundingUrl": "https://ko-fi.com/jparkerweb",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
|
||||
@@ -0,0 +1,743 @@
|
||||
/* ============================ */
|
||||
/* == 🚩 Pixel Banner Styles == */
|
||||
/* ============================ */
|
||||
@keyframes pixel-banner-spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
@keyframes pixel-banner-fade-in {
|
||||
0% { opacity: 0; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
.pixel-banner-icon-fade-in {
|
||||
animation: pixel-banner-fade-in 0.4s ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes pixel-banner-icon-fade-in {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 0.35; }
|
||||
}
|
||||
|
||||
@keyframes pixel-banner-twinkle {
|
||||
0% { opacity: 1; transform: scale(1) rotate(0deg); }
|
||||
20% { opacity: 0.8; transform: scale(1.3) rotate(10deg); }
|
||||
40% { opacity: 1; transform: scale(1.1) rotate(5deg); }
|
||||
60% { opacity: 0.8; transform: scale(1.3) rotate(-5deg); }
|
||||
80% { opacity: 1; transform: scale(1.1) rotate(-10deg); }
|
||||
100% { opacity: 1; transform: scale(1) rotate(0deg); }
|
||||
}
|
||||
|
||||
@keyframes pixel-banner-radial-pulse {
|
||||
0% { box-shadow: 0 0; }
|
||||
60% { box-shadow: 0 0 hsla(var(--accent-h), var(--accent-s), var(--accent-l), 1); }
|
||||
90% { box-shadow: 0 0 0 4px hsla(var(--accent-h), var(--accent-s), var(--accent-l), 0.5); }
|
||||
100% { box-shadow: 0 0 0 2px hsla(var(--accent-h), var(--accent-s), var(--accent-l), 0.2); }
|
||||
}
|
||||
|
||||
@keyframes pixel-banner-scale-up-down {
|
||||
0% { transform: scale(1); }
|
||||
50% { transform: scale(1.1); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
.pixel-banner-image {
|
||||
position: absolute !important;
|
||||
top: 0;
|
||||
left: var(--pixel-banner-banner-gap, 0);
|
||||
right: var(--pixel-banner-banner-gap, 0);
|
||||
background-size: cover;
|
||||
background-position: var(--pixel-banner-x-position, 50%) var(--pixel-banner-y-position, 50%) !important;
|
||||
overflow: hidden;
|
||||
mask-image: linear-gradient(to bottom, black calc(100% + var(--pixel-banner-fade, -75%)), transparent);
|
||||
-webkit-mask-image: linear-gradient(to bottom, black calc(100% + var(--pixel-banner-fade, -75%)), transparent);
|
||||
height: var(--pixel-banner-height, 350px);
|
||||
border-radius: var(--pixel-banner-radius, 17px) !important;
|
||||
pointer-events: none;
|
||||
animation: pixel-banner-fade-in var(--pixel-banner-fade-in-animation-duration, 300ms) ease-in-out;
|
||||
will-change: opacity;
|
||||
transform: translateZ(0);
|
||||
background-repeat: no-repeat;
|
||||
z-index: -1;
|
||||
width: unset !important;
|
||||
max-width: var(--pixel-banner-max-width, unset) !important;
|
||||
margin: var(--pixel-banner-alignment, 0 auto);
|
||||
/* add transition to banner image background position */
|
||||
transition: background-position 0.5s ease;
|
||||
}
|
||||
|
||||
.pixel-banner-video {
|
||||
object-fit: cover;
|
||||
object-position: var(--pixel-banner-x-position, 50%) var(--pixel-banner-y-position, 50%) !important;
|
||||
}
|
||||
|
||||
.markdown-embed-content .markdown-preview-view {
|
||||
min-height: var(--pixel-banner-embed-min-height, unset) !important;
|
||||
}
|
||||
.markdown-embed-content .pixel-banner-image {
|
||||
position: absolute !important;
|
||||
left: 0 !important;
|
||||
z-index: unset !important;
|
||||
}
|
||||
.markdown-embed-content .pixel-banner-image ~ div {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* collapse scrollbar gutter when no scrollbar is present */
|
||||
.pixel-banner .markdown-preview-view,
|
||||
.pixel-banner .markdown-source-view .cm-scroller {
|
||||
scrollbar-gutter: auto !important;
|
||||
}
|
||||
|
||||
/* Apply title color to both reading and editing mode */
|
||||
.pixel-banner div.inline-title,
|
||||
.pixel-banner .markdown-source-view div.inline-title {
|
||||
color: var(--pixel-banner-title-color, var(--inline-title-color));
|
||||
}
|
||||
|
||||
/* fix for banner image overlapping with note content */
|
||||
/* isolate the banner image from the note content */
|
||||
.view-content.pixel-banner {
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------- */
|
||||
/* -- Specific styles for hover popover banners -- */
|
||||
/* ----------------------------------------------- */
|
||||
.popover.hover-popover {
|
||||
min-height: 200px !important;
|
||||
}
|
||||
.popover.hover-popover .pixel-banner-image {
|
||||
background-repeat: repeat !important;
|
||||
min-height: 100px !important;
|
||||
}
|
||||
.pixel-banner-image + .markdown-preview-sizer.markdown-preview-section {
|
||||
margin-top: 100px !important;
|
||||
}
|
||||
.hover-popover .markdown-preview-view.pixel-banner {
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
}
|
||||
.hover-popover .pixel-banner-image {
|
||||
position: absolute !important;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 0;
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
border-radius: var(--pixel-banner-radius, 17px) !important;
|
||||
}
|
||||
.hover-popover .markdown-preview-view .markdown-preview-sizer {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.hover-popover .markdown-preview-view.pixel-banner .markdown-preview-sizer {
|
||||
padding-top: var(--pixel-banner-content-start, 150px) !important;
|
||||
}
|
||||
/* ----------------------------------------------- */
|
||||
|
||||
.cm-sizer .metadata-container,
|
||||
.markdown-preview-sizer .metadata-container {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* fix overflow issue with embedded notes */
|
||||
.internal-embed:not(.image-embed),
|
||||
.internal-embed:not(.image-embed) > .markdown-embed-content > .markdown-preview-view {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* hide frontmatter fields in reading mode */
|
||||
.markdown-preview-view .pixel-banner-hidden-field {
|
||||
display: none !important;
|
||||
}
|
||||
/* Add specific targeting for properties view */
|
||||
.metadata-property.pixel-banner-hidden-field {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------- */
|
||||
/* -- content start (push frontmatter container down) -- */
|
||||
/* *** NOTE: this is now handled in bannerManager.js *** */
|
||||
/* *** for faster rendering! *** */
|
||||
/* ----------------------------------------------------- */
|
||||
/* .view-content.pixel-banner > .markdown-source-view .cm-sizer,
|
||||
.view-content.pixel-banner > .markdown-reading-view .markdown-preview-sizer {
|
||||
padding-top: var(--pixel-banner-content-start, 355px) !important;
|
||||
padding-bottom: 0 !important;
|
||||
} */
|
||||
/* -- fix for embedded notes -- */
|
||||
.internal-embed > .markdown-embed-content .cm-sizer:first-of-type,
|
||||
.internal-embed > .markdown-embed-content .markdown-preview-sizer:first-of-type {
|
||||
padding-top: unset !important;
|
||||
}
|
||||
.internal-embed > .markdown-embed-content .cm-sizer:first-of-type > .pixel-banner-image ~ .markdown-preview-pusher,
|
||||
.internal-embed > .markdown-embed-content .markdown-preview-sizer:first-of-type > .pixel-banner-image ~ .markdown-preview-pusher {
|
||||
height: var(--pixel-banner-content-start, 0.1px) !important;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------- */
|
||||
/* -- Settings Page Styles -- */
|
||||
/* -------------------------- */
|
||||
.vertical-tab-content-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.pixel-banner-settings {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
padding: 20px;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.pixel-banner-header {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
background-color: var(--background-secondary);
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.pixel-banner-header h2 {
|
||||
margin-bottom: 10px;
|
||||
color: var(--text-accent);
|
||||
}
|
||||
|
||||
.pixel-banner-main-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.pixel-banner-settings-tabs {
|
||||
flex-direction: row;
|
||||
flex: 0 auto;
|
||||
}
|
||||
|
||||
.pixel-banner-settings-tab-content-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.pixel-banner-settings-tab-content-container > .tab-content {
|
||||
overflow: auto;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.tab-content[data-tab="Folder Images"] {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.tab-content[data-tab="Folder Images"] .add-folder-image-setting {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 64px;
|
||||
padding-right: 16px;
|
||||
background: var(--color-secondary);
|
||||
}
|
||||
.tab-content[data-tab="Folder Images"] .add-folder-image-setting button {
|
||||
color: var(--text-on-accent);
|
||||
border-bottom: 2px solid var(--text-accent-hover);
|
||||
background: var(--color-accent);
|
||||
}
|
||||
|
||||
.pixel-banner-section {
|
||||
background-color: var(--background-secondary);
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.pixel-banner-section h3 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 15px;
|
||||
color: var(--text-accent-hover);
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.pixel-banner-section ol {
|
||||
padding-left: 20px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.pixel-banner-section pre {
|
||||
background-color: var(--background-primary);
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.pixel-banner-footer {
|
||||
margin-top: 30px;
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.pixel-banner-settings .setting-item {
|
||||
border-top: none;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.pixel-banner-settings .setting-item.full-width-control,
|
||||
.pixel-banner-settings .setting-item.full-width-control > .setting-item-control {
|
||||
width: 100%;
|
||||
}
|
||||
.pixel-banner-settings .setting-item-control {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.setting-item.folder-image-setting {
|
||||
position: relative;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
border: 1px solid var(--slider-track-background);
|
||||
border-radius: 5px;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
/* background-color: var(--background-secondary); */
|
||||
}
|
||||
.setting-item.folder-image-setting .folder-image-delete-container {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 0;
|
||||
}
|
||||
.pixel-banner-setting--delete-button {
|
||||
border: 1px solid var(--color-accent) !important;
|
||||
}
|
||||
.pixel-banner-setting--delete-button:hover {
|
||||
background: var(--color-accent) !important;
|
||||
color: var(--text-on-accent) !important;
|
||||
}
|
||||
|
||||
.setting-item.folder-image-setting > .folder-input-container,
|
||||
.setting-item.folder-image-setting > .display-and-repeat-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
.setting-item.folder-image-setting > .setting-item-control {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
/* setting item for api key */
|
||||
.pixel-banner-settings .setting-item[data-id="apiKey"] .setting-item-control {
|
||||
width: 100%;
|
||||
}
|
||||
/* setting item for default keywords */
|
||||
.pixel-banner-settings .setting-item[data-id="defaultKeywords"] .setting-item-control {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.pixel-banner-settings input[type="text"],
|
||||
.pixel-banner-settings select {
|
||||
background-color: var(--background-primary);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 5px;
|
||||
padding: 5px 30px 5px 10px;
|
||||
}
|
||||
|
||||
.pixel-banner-settings .dropdown {
|
||||
background-color: var(--background-primary);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.pixel-banner-settings .slider-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pixel-banner-settings.slider-value {
|
||||
min-width: 30px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.pixel-banner-settings .setting-item-description {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.pixel-banner-settings .pixel-banner-example-values {
|
||||
color: var(--code-comment, var(--text-muted, inherit));
|
||||
}
|
||||
|
||||
.pixel-banner-settings-tabs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.pixel-banner-settings-tab {
|
||||
margin: 0 10px 10px 0;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
text-transform: uppercase;
|
||||
color: var(--text-muted);
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.pixel-banner-settings-tab:hover {
|
||||
color: var(--text-normal);
|
||||
}
|
||||
|
||||
.pixel-banner-settings-tab.active {
|
||||
color: var(--text-on-accent);
|
||||
border-bottom: 2px solid var(--text-accent-hover);
|
||||
background: var(--color-accent);
|
||||
}
|
||||
|
||||
.pixel-banner-settings-tab-content-container > .tab-content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.pixel-banner-settings-tab-content-container > .tab-content.active {
|
||||
display: block;
|
||||
}
|
||||
.pixel-banner-settings-tabs .folder-image-setting .slider-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pixel-banner-settings-tabs .folder-image-setting .slider-value {
|
||||
min-width: 30px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.folder-images-container .setting-item-name__label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.folder-images-container .full-width-control {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.setting-item.folder-image-setting > div { min-height: 50px; }
|
||||
|
||||
.pixel-banner-settings .tab-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.pixel-banner-settings .tab-callout {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 1;
|
||||
margin: 0 0 1em;
|
||||
padding: .5em 1em;
|
||||
background-color: var(--background-primary-alt);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 5px;
|
||||
color: var(--text-accent-hover);
|
||||
}
|
||||
|
||||
.pixel-banner-settings .setting-item {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.pixel-banner-settings input,
|
||||
.pixel-banner-settings textarea,
|
||||
.pixel-banner-settings select {
|
||||
z-index: 3;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.metadata-container.pixel-banner-hidden-section {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.pixel-banner-settings .setting-group {
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 6px;
|
||||
padding: 12px;
|
||||
margin: 12px 0;
|
||||
}
|
||||
|
||||
.pixel-banner-settings .setting-dependent {
|
||||
margin-left: 24px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.pixel-banner-settings .setting-dependent::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: -24px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 2px;
|
||||
background-color: var(--background-modifier-border);
|
||||
}
|
||||
|
||||
.pixel-banner-settings .setting-dependent.is-disabled {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.pixel-banner-twinkle-animation {
|
||||
animation: pixel-banner-twinkle 2s infinite;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.pixel-banner-image-container {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 4px;
|
||||
padding: 8px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.pixel-banner-image-container:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
background-color: var(--background-modifier-hover);
|
||||
}
|
||||
|
||||
.pixel-banner-image-container {
|
||||
margin-top: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pixel-banner-loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.pixel-banner-error {
|
||||
color: var(--text-accent);
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* Loading Spinner */
|
||||
.dot-pulse {
|
||||
position: relative;
|
||||
left: -9999px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
background-color: var(--text-accent);
|
||||
color: var(--text-accent);
|
||||
box-shadow: 9999px 0 0 -4px;
|
||||
animation: pixel-banner-dot-pulse 1.5s infinite linear;
|
||||
animation-delay: 0.25s;
|
||||
}
|
||||
|
||||
.dot-pulse::before, .dot-pulse::after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
background-color: var(--text-accent);
|
||||
color: var(--text-accent);
|
||||
}
|
||||
|
||||
.dot-pulse::before {
|
||||
box-shadow: 9984px 0 0 -4px;
|
||||
animation: pixel-banner-dot-pulse-before 1.5s infinite linear;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.dot-pulse::after {
|
||||
box-shadow: 10014px 0 0 -4px;
|
||||
animation: pixel-banner-dot-pulse-after 1.5s infinite linear;
|
||||
animation-delay: 0.5s;
|
||||
}
|
||||
|
||||
@keyframes pixel-banner-dot-pulse-before {
|
||||
0% { box-shadow: 9984px 0 0 -4px; }
|
||||
30% { box-shadow: 9984px 0 0 2px; }
|
||||
60%, 100% { box-shadow: 9984px 0 0 -4px; }
|
||||
}
|
||||
|
||||
@keyframes pixel-banner-dot-pulse {
|
||||
0% { box-shadow: 9999px 0 0 -4px; }
|
||||
30% { box-shadow: 9999px 0 0 2px; }
|
||||
60%, 100% { box-shadow: 9999px 0 0 -4px; }
|
||||
}
|
||||
|
||||
@keyframes pixel-banner-dot-pulse-after {
|
||||
0% { box-shadow: 10014px 0 0 -4px; }
|
||||
30% { box-shadow: 10014px 0 0 2px; }
|
||||
60%, 100% { box-shadow: 10014px 0 0 -4px; }
|
||||
}
|
||||
|
||||
@keyframes pixel-banner-token-bounce {
|
||||
0% { transform: scale(1); }
|
||||
50% { transform: scale(1.2); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
@keyframes pixel-banner-token-glow {
|
||||
0% { text-shadow: 0 0 0px rgba(255, 215, 0, 0); }
|
||||
50% { text-shadow: 0 0 15px var(--text-accent-hover); }
|
||||
100% { text-shadow: 0 0 0px rgba(255, 215, 0, 0); }
|
||||
}
|
||||
|
||||
.token-balance-animation {
|
||||
animation: pixel-banner-token-bounce 0.7s cubic-bezier(0.175, 0.885, 0.32, 1.275), pixel-banner-token-glow 0.7s ease-in-out;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.radial-pulse-animation {
|
||||
box-shadow: 0 0;
|
||||
animation-delay: 0ms;
|
||||
animation-duration: 3.4s;
|
||||
animation-direction: normal;
|
||||
animation-iteration-count: infinite;
|
||||
animation-name: pixel-banner-radial-pulse;
|
||||
}
|
||||
|
||||
/* animation for an element to scale up and down */
|
||||
.pixel-banner-scale-up-down-animation {
|
||||
animation: pixel-banner-scale-up-down 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* --------------------------- */
|
||||
/* -- top left icon buttons -- */
|
||||
/* --------------------------- */
|
||||
.select-image-icon,
|
||||
.pin-icon,
|
||||
.refresh-icon,
|
||||
.view-image-icon {
|
||||
z-index: var(--layer-modal);
|
||||
opacity: 0.35;
|
||||
transition: all 0.4s ease-in-out;
|
||||
animation: pixel-banner-icon-fade-in 0.4s ease-in-out;
|
||||
width: unset !important;
|
||||
}
|
||||
.select-image-icon:hover,
|
||||
.pin-icon:hover,
|
||||
.refresh-icon:hover,
|
||||
.view-image-icon:hover {
|
||||
opacity: 1 !important;
|
||||
cursor: pointer;
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
/* ------------------------- */
|
||||
/* -- banner icon overlay -- */
|
||||
/* ------------------------- */
|
||||
.banner-icon-overlay {
|
||||
--pixel-banner-icon-translate-x: calc(var(--pixel-banner-icon-x) * -1);
|
||||
transform: translate(var(--pixel-banner-icon-translate-x), -15%) rotate(var(--pixel-banner-icon-rotate, 0deg));
|
||||
transform-origin: center !important;
|
||||
position: absolute !important;
|
||||
top: var(--pixel-banner-icon-start);
|
||||
left: var(--pixel-banner-icon-x, 25%);
|
||||
margin-top: calc(var(--pixel-banner-icon-vertical-offset, 0) * 1px);
|
||||
padding-top: var(--pixel-banner-icon-padding-y, 0) !important;
|
||||
padding-right: var(--pixel-banner-icon-padding-x, 0) !important;
|
||||
padding-bottom: var(--pixel-banner-icon-padding-y, 0) !important;
|
||||
padding-left: var(--pixel-banner-icon-padding-x, 0) !important;
|
||||
opacity: var(--pixel-banner-icon-opacity, 100%);
|
||||
color: var(--pixel-banner-icon-color, var(--text-normal));
|
||||
font-size: var(--pixel-banner-icon-size, 70px);
|
||||
font-weight: var(--pixel-banner-icon-font-weight, normal);
|
||||
background: var(--pixel-banner-icon-background-color, unset);
|
||||
border-radius: var(--pixel-banner-icon-border-radius, 17px);
|
||||
white-space: nowrap;
|
||||
text-wrap: pretty;
|
||||
word-break: break-word;
|
||||
width: max-content !important;
|
||||
max-width: var(--pixel-banner-width) !important;
|
||||
pointer-events: none;
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
flex-wrap: nowrap;
|
||||
text-wrap: nowrap;
|
||||
}
|
||||
/* banner icon image */
|
||||
.banner-icon-overlay > img {
|
||||
height: var(--pixel-banner-icon-image-size-multiplier, 1em);
|
||||
}
|
||||
/* banner icon text */
|
||||
.banner-icon-overlay > .banner-icon-text {
|
||||
position: relative;
|
||||
top: var(--pixel-banner-icon-text-vertical-offset, 0);
|
||||
line-height: var(--pixel-banner-icon-size, 1);
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------- */
|
||||
/* -- various plugin conflict fixes -- */
|
||||
/* ----------------------------------- */
|
||||
/* hide banner images and related icons in search-result-container */
|
||||
.search-result-container .select-image-icon,
|
||||
.search-result-container .pin-icon,
|
||||
.search-result-container .refresh-icon,
|
||||
.search-result-container .view-image-icon,
|
||||
.search-result-container .banner-icon-overlay,
|
||||
.search-result-container .pixel-banner-image {
|
||||
display: none !important;
|
||||
}
|
||||
/* better search views ⇢ hide banner images and related icons in backlink-pane / outgoing-link-pane */
|
||||
.backlink-pane .select-image-icon,
|
||||
.backlink-pane .pin-icon,
|
||||
.backlink-pane .refresh-icon,
|
||||
.backlink-pane .view-image-icon,
|
||||
.backlink-pane .banner-icon-overlay,
|
||||
.backlink-pane .pixel-banner-image {
|
||||
display: none !important;
|
||||
}
|
||||
.outgoing-link-pane .select-image-icon,
|
||||
.outgoing-link-pane .pin-icon,
|
||||
.outgoing-link-pane .refresh-icon,
|
||||
.outgoing-link-pane .view-image-icon,
|
||||
.outgoing-link-pane .banner-icon-overlay,
|
||||
.outgoing-link-pane .pixel-banner-image {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
/* ========================= */
|
||||
/* == misc helper classes == */
|
||||
/* ========================= */
|
||||
.display-none { display: none !important; }
|
||||
|
||||
.margin-top-0 { margin-top: 0px !important; }
|
||||
.margin-top-5 { margin-top: 5px !important; }
|
||||
.margin-top-10 { margin-top: 10px !important; }
|
||||
.margin-top-20 { margin-top: 20px !important; }
|
||||
.margin-top-40 { margin-top: 40px !important; }
|
||||
.margin-right-0 { margin-right: 0px !important; }
|
||||
.margin-right-5 { margin-right: 5px !important; }
|
||||
.margin-right-10 { margin-right: 10px !important; }
|
||||
.margin-right-20 { margin-right: 20px !important; }
|
||||
.margin-right-40 { margin-right: 40px !important; }
|
||||
.margin-left-0 { margin-left: 0px !important; }
|
||||
.margin-left-5 { margin-left: 5px !important; }
|
||||
.margin-left-10 { margin-left: 10px !important; }
|
||||
.margin-left-20 { margin-left: 20px !important; }
|
||||
.margin-left-40 { margin-left: 40px !important; }
|
||||
.margin-bottom-0 { margin-bottom: 0px !important; }
|
||||
.margin-bottom-5 { margin-bottom: 5px !important; }
|
||||
.margin-bottom-10 { margin-bottom: 10px !important; }
|
||||
.margin-bottom-20 { margin-bottom: 20px !important; }
|
||||
.margin-bottom-40 { margin-bottom: 40px !important; }
|
||||
|
||||
.width-100 { width: 100% !important; }
|
||||
|
||||
.cursor-pointer { cursor: pointer !important; }
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "Obsidianite",
|
||||
"version": "2.0.2",
|
||||
"minAppVersion": "1.1.0",
|
||||
"author": "@bennyxguo",
|
||||
"authorUrl": "https://github.com/bennyxguo"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "Obuntu",
|
||||
"version": "0.0.0",
|
||||
"minAppVersion": "0.16.0",
|
||||
"author": "Dubinin Dmitry"
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
{
|
||||
"main": {
|
||||
"id": "07631e59d04fef0d",
|
||||
"type": "split",
|
||||
"children": [
|
||||
{
|
||||
"id": "ac63da24252f524e",
|
||||
"type": "tabs",
|
||||
"children": [
|
||||
{
|
||||
"id": "ec486ba0721f6e6a",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "markdown",
|
||||
"state": {
|
||||
"file": "Master_Project_log.md",
|
||||
"mode": "source",
|
||||
"source": false
|
||||
},
|
||||
"icon": "lucide-file",
|
||||
"title": "Master_Project_log"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"direction": "vertical"
|
||||
},
|
||||
"left": {
|
||||
"id": "962e606c5f9294a7",
|
||||
"type": "split",
|
||||
"children": [
|
||||
{
|
||||
"id": "da0525fce517781b",
|
||||
"type": "tabs",
|
||||
"children": [
|
||||
{
|
||||
"id": "5a7871b6cd13ece2",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "file-explorer",
|
||||
"state": {
|
||||
"sortOrder": "alphabetical",
|
||||
"autoReveal": false
|
||||
},
|
||||
"icon": "lucide-folder-closed",
|
||||
"title": "Files"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "ff273e47b1898830",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "search",
|
||||
"state": {
|
||||
"query": "",
|
||||
"matchingCase": false,
|
||||
"explainSearch": false,
|
||||
"collapseAll": false,
|
||||
"extraContext": false,
|
||||
"sortOrder": "alphabetical"
|
||||
},
|
||||
"icon": "lucide-search",
|
||||
"title": "Search"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "214432a66def5c52",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "bookmarks",
|
||||
"state": {},
|
||||
"icon": "lucide-bookmark",
|
||||
"title": "Bookmarks"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"direction": "horizontal",
|
||||
"width": 200
|
||||
},
|
||||
"right": {
|
||||
"id": "ee9fef0715a301b6",
|
||||
"type": "split",
|
||||
"children": [
|
||||
{
|
||||
"id": "6ab66e0f443d6d28",
|
||||
"type": "tabs",
|
||||
"children": [
|
||||
{
|
||||
"id": "8e045092ef19e07b",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "backlink",
|
||||
"state": {
|
||||
"file": "MASTER_PROJECT_LOG.md",
|
||||
"collapseAll": false,
|
||||
"extraContext": false,
|
||||
"sortOrder": "alphabetical",
|
||||
"showSearch": false,
|
||||
"searchQuery": "",
|
||||
"backlinkCollapsed": false,
|
||||
"unlinkedCollapsed": true
|
||||
},
|
||||
"icon": "links-coming-in",
|
||||
"title": "Backlinks for MASTER_PROJECT_LOG"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "2a7818ef96ce860a",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "outgoing-link",
|
||||
"state": {
|
||||
"file": "MASTER_PROJECT_LOG.md",
|
||||
"linksCollapsed": false,
|
||||
"unlinkedCollapsed": true
|
||||
},
|
||||
"icon": "links-going-out",
|
||||
"title": "Outgoing links from MASTER_PROJECT_LOG"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "1aa8c310e14cd7e7",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "tag",
|
||||
"state": {
|
||||
"sortOrder": "frequency",
|
||||
"useHierarchy": true,
|
||||
"showSearch": false,
|
||||
"searchQuery": ""
|
||||
},
|
||||
"icon": "lucide-tags",
|
||||
"title": "Tags"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "44ad0ea68f1500ec",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "all-properties",
|
||||
"state": {
|
||||
"sortOrder": "frequency",
|
||||
"showSearch": false,
|
||||
"searchQuery": ""
|
||||
},
|
||||
"icon": "lucide-archive",
|
||||
"title": "All properties"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "6c685d74064c7a4b",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "outline",
|
||||
"state": {
|
||||
"file": "MASTER_PROJECT_LOG.md",
|
||||
"followCursor": false,
|
||||
"showSearch": false,
|
||||
"searchQuery": ""
|
||||
},
|
||||
"icon": "lucide-list",
|
||||
"title": "Outline of MASTER_PROJECT_LOG"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"direction": "horizontal",
|
||||
"width": 300,
|
||||
"collapsed": true
|
||||
},
|
||||
"left-ribbon": {
|
||||
"hiddenItems": {
|
||||
"switcher:Open quick switcher": false,
|
||||
"graph:Open graph view": false,
|
||||
"canvas:Create new canvas": false,
|
||||
"daily-notes:Open today's daily note": false,
|
||||
"templates:Insert template": false,
|
||||
"command-palette:Open command palette": false,
|
||||
"bases:Create new base": false,
|
||||
"pexels-banner:🚩 Pixel Banner Menu": false
|
||||
}
|
||||
},
|
||||
"active": "ec486ba0721f6e6a",
|
||||
"lastOpenFiles": [
|
||||
"Untitled.md",
|
||||
"Master_Project_log.md",
|
||||
"Time Line.md",
|
||||
"MASTER_PROJECT_LOG.md",
|
||||
"banner/wp4254880-dark-4k-wallpapers.jpg",
|
||||
"pixel-banner-images/wp4254880-dark-4k-wallpapers.jpg",
|
||||
"pixel-banner-images",
|
||||
"banner",
|
||||
"New folder",
|
||||
"MASTER_PROJECT_LOG.md.tmp.34284.1775683046595"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
@@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
@@ -0,0 +1 @@
|
||||
My Journal
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AndroidProjectSystem">
|
||||
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,123 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<JetCodeStyleSettings>
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
<arrangement>
|
||||
<rules>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:android</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:id</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>style</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>ANDROID_ATTRIBUTE_ORDER</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
</rules>
|
||||
</arrangement>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
@@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="21" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="deploymentTargetSelector">
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DialogSelection />
|
||||
</SelectionState>
|
||||
</selectionStates>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,61 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="ComposePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="ComposePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="ComposePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="ComposePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="GlancePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="GlancePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="GlancePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="GlancePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewDeviceShouldUseNewSpec" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewFontScaleMustBeGreaterThanZero" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewParameterProviderOnFirstParameter" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
||||
@@ -0,0 +1,9 @@
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
|
||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
|
||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="StudioBotProjectSettings">
|
||||
<option name="shareContext" value="OptedIn" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1 @@
|
||||
/build
|
||||
@@ -0,0 +1,58 @@
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.compose)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.example.myjournal"
|
||||
compileSdk {
|
||||
version = release(36) {
|
||||
minorApiLevel = 1
|
||||
}
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.example.myjournal"
|
||||
minSdk = 24
|
||||
targetSdk = 36
|
||||
versionCode = 1
|
||||
versionName = "1.0"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
buildFeatures {
|
||||
compose = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.androidx.core.ktx)
|
||||
implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||
implementation(libs.androidx.activity.compose)
|
||||
implementation(platform(libs.androidx.compose.bom))
|
||||
implementation(libs.androidx.compose.ui)
|
||||
implementation(libs.androidx.compose.ui.graphics)
|
||||
implementation(libs.androidx.compose.ui.tooling.preview)
|
||||
implementation(libs.androidx.compose.material3)
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
androidTestImplementation(libs.androidx.espresso.core)
|
||||
androidTestImplementation(platform(libs.androidx.compose.bom))
|
||||
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
|
||||
debugImplementation(libs.androidx.compose.ui.tooling)
|
||||
debugImplementation(libs.androidx.compose.ui.test.manifest)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.example.myjournal
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.example.myjournal", appContext.packageName)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.MyJournal">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.MyJournal">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.example.myjournal
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.example.myjournal.ui.theme.MyJournalTheme
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
setContent {
|
||||
MyJournalTheme {
|
||||
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
|
||||
Greeting(
|
||||
name = "Android",
|
||||
modifier = Modifier.padding(innerPadding)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Greeting(name: String, modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
text = "Hello $name!",
|
||||
modifier = modifier
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun GreetingPreview() {
|
||||
MyJournalTheme {
|
||||
Greeting("Android")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.example.myjournal.ui.theme
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
val Purple80 = Color(0xFFD0BCFF)
|
||||
val PurpleGrey80 = Color(0xFFCCC2DC)
|
||||
val Pink80 = Color(0xFFEFB8C8)
|
||||
|
||||
val Purple40 = Color(0xFF6650a4)
|
||||
val PurpleGrey40 = Color(0xFF625b71)
|
||||
val Pink40 = Color(0xFF7D5260)
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.example.myjournal.ui.theme
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.material3.dynamicDarkColorScheme
|
||||
import androidx.compose.material3.dynamicLightColorScheme
|
||||
import androidx.compose.material3.lightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
|
||||
private val DarkColorScheme = darkColorScheme(
|
||||
primary = Purple80,
|
||||
secondary = PurpleGrey80,
|
||||
tertiary = Pink80
|
||||
)
|
||||
|
||||
private val LightColorScheme = lightColorScheme(
|
||||
primary = Purple40,
|
||||
secondary = PurpleGrey40,
|
||||
tertiary = Pink40
|
||||
|
||||
/* Other default colors to override
|
||||
background = Color(0xFFFFFBFE),
|
||||
surface = Color(0xFFFFFBFE),
|
||||
onPrimary = Color.White,
|
||||
onSecondary = Color.White,
|
||||
onTertiary = Color.White,
|
||||
onBackground = Color(0xFF1C1B1F),
|
||||
onSurface = Color(0xFF1C1B1F),
|
||||
*/
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun MyJournalTheme(
|
||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
// Dynamic color is available on Android 12+
|
||||
dynamicColor: Boolean = true,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
val colorScheme = when {
|
||||
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
||||
val context = LocalContext.current
|
||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
||||
}
|
||||
|
||||
darkTheme -> DarkColorScheme
|
||||
else -> LightColorScheme
|
||||
}
|
||||
|
||||
MaterialTheme(
|
||||
colorScheme = colorScheme,
|
||||
typography = Typography,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.example.myjournal.ui.theme
|
||||
|
||||
import androidx.compose.material3.Typography
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
// Set of Material typography styles to start with
|
||||
val Typography = Typography(
|
||||
bodyLarge = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 16.sp,
|
||||
lineHeight = 24.sp,
|
||||
letterSpacing = 0.5.sp
|
||||
)
|
||||
/* Other default text styles to override
|
||||
titleLarge = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 22.sp,
|
||||
lineHeight = 28.sp,
|
||||
letterSpacing = 0.sp
|
||||
),
|
||||
labelSmall = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 11.sp,
|
||||
lineHeight = 16.sp,
|
||||
letterSpacing = 0.5.sp
|
||||
)
|
||||
*/
|
||||
)
|
||||
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
||||
@@ -0,0 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 982 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="purple_200">#FFBB86FC</color>
|
||||
<color name="purple_500">#FF6200EE</color>
|
||||
<color name="purple_700">#FF3700B3</color>
|
||||
<color name="teal_200">#FF03DAC5</color>
|
||||
<color name="teal_700">#FF018786</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
</resources>
|
||||
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">My Journal</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="Theme.MyJournal" parent="android:Theme.Material.Light.NoActionBar" />
|
||||
</resources>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample backup rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/guide/topics/data/autobackup
|
||||
for details.
|
||||
Note: This file is ignored for devices older than API 31
|
||||
See https://developer.android.com/about/versions/12/backup-restore
|
||||
-->
|
||||
<full-backup-content>
|
||||
<!--
|
||||
<include domain="sharedpref" path="."/>
|
||||
<exclude domain="sharedpref" path="device.xml"/>
|
||||
-->
|
||||
</full-backup-content>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample data extraction rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
|
||||
for details.
|
||||
-->
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<!-- TODO: Use <include> and <exclude> to control what is backed up.
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
-->
|
||||
</cloud-backup>
|
||||
<!--
|
||||
<device-transfer>
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
</device-transfer>
|
||||
-->
|
||||
</data-extraction-rules>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.example.myjournal
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
alias(libs.plugins.android.application) apply false
|
||||
alias(libs.plugins.kotlin.compose) apply false
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. For more details, visit
|
||||
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
|
||||
# org.gradle.parallel=true
|
||||
# Kotlin code style for this project: "official" or "obsolete":
|
||||
kotlin.code.style=official
|
||||
@@ -0,0 +1,12 @@
|
||||
#This file is generated by updateDaemonJvm
|
||||
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/ec7520a1e057cd116f9544c42142a16b/redirect
|
||||
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/4c4f879899012ff0a8b2e2117df03b0e/redirect
|
||||
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/ec7520a1e057cd116f9544c42142a16b/redirect
|
||||
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/4c4f879899012ff0a8b2e2117df03b0e/redirect
|
||||
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/73bcfb608d1fde9fb62e462f834a3299/redirect
|
||||
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/846ee0d876d26a26f37aa1ce8de73224/redirect
|
||||
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/ec7520a1e057cd116f9544c42142a16b/redirect
|
||||
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/4c4f879899012ff0a8b2e2117df03b0e/redirect
|
||||
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/9482ddec596298c84656d31d16652665/redirect
|
||||
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/39701d92e1756bb2f141eb67cd4c660e/redirect
|
||||
toolchainVersion=21
|
||||
@@ -0,0 +1,31 @@
|
||||
[versions]
|
||||
agp = "9.1.0"
|
||||
coreKtx = "1.10.1"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "1.1.5"
|
||||
espressoCore = "3.5.1"
|
||||
lifecycleRuntimeKtx = "2.6.1"
|
||||
activityCompose = "1.8.0"
|
||||
kotlin = "2.2.10"
|
||||
composeBom = "2026.02.01"
|
||||
|
||||
[libraries]
|
||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
||||
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
|
||||
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
|
||||
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
|
||||
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" }
|
||||
androidx-compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
|
||||
androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
|
||||
androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
|
||||
androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
|
||||
androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
||||
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#Wed Apr 08 13:52:45 EDT 2026
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=b266d5ff6b90eada6dc3b20cb090e3731302e553a27c5d3e4df1f0d76beaff06
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -0,0 +1,251 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH="\\\"\\\""
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
@@ -0,0 +1,94 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -0,0 +1,26 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
google {
|
||||
content {
|
||||
includeGroupByRegex("com\\.android.*")
|
||||
includeGroupByRegex("com\\.google.*")
|
||||
includeGroupByRegex("androidx.*")
|
||||
}
|
||||
}
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
plugins {
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
|
||||
}
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "My Journal"
|
||||
include(":app")
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(dir \"C:\\\\Users\\\\jbrock\\\\Documents\\\\pisyncfolder\\\\JournalApp\" /s /b *.html)",
|
||||
"Bash(grep -oP '#[0-9a-fA-F]{3,6}' \"C:\\\\Users\\\\jbrock\\\\Documents\\\\pisyncfolder\\\\JournalApp\\\\JournalAppPrototype\\\\journal.html\")",
|
||||
"Bash(grep -oE '#[0-9a-fA-F]{3,6}' \"C:\\\\Users\\\\jbrock\\\\Documents\\\\pisyncfolder\\\\JournalApp\\\\JournalAppPrototype\\\\journal.html\")"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,355 @@
|
||||
---
|
||||
banner: pixel-banner-images/wp4254880-dark-4k-wallpapers.jpg
|
||||
banner-height: 460
|
||||
pixel-banner-flag-color: white
|
||||
---
|
||||
# Journal App — Dev Log
|
||||
|
||||
> Single-file offline journal with timeline UI, calendar navigation, and markdown export.
|
||||
> Stack: Pure HTML/CSS/JS · IndexedDB · No dependencies
|
||||
> File: `C:\Users\jbrock\Documents\pisyncfolder\Journal App\journal.html`
|
||||
|
||||
---
|
||||
|
||||
## Status
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Version | v1.10 |
|
||||
| Status | Active Development |
|
||||
| Started | April 7, 2026 |
|
||||
| Last Updated | April 27, 2026 (v1.10) |
|
||||
|
||||
---
|
||||
|
||||
## Changelog
|
||||
|
||||
### v1.10 — April 27, 2026
|
||||
- **Project card timeline connector** — CSS-only horizontal connector line extending from each breakout card's left edge back to the main timeline vertical line; implemented via `.breakout-card::before` (205px accent-colored line at 50% card height, opacity 0.5) and `.breakout-card::after` (12px dot centered on the timeline line at `left: -211px`); `position: relative` added to `.breakout-card`; no layout constraints broken
|
||||
- **Breakout card inline rename** — `edit` button added to breakout card action row (between `open →` and `✕`); clicking it swaps the project name display to a `.breakout-name-input` field and replaces action buttons with `save`/`cancel`; save writes both the `projectName` field on the breakout entry (`updateEntry`) and the canonical name in the projects store (`updateProject`), then refreshes the project cache and re-renders; `Enter` submits, `Escape` cancels; `updateProject(id, fields)` added as a new DB helper on `PROJECTS_STORE`
|
||||
|
||||
### v1.9 — April 21, 2026
|
||||
- **CSS custom properties** — all 8 theme colors now defined as CSS variables in `:root` (`--bg-primary`, `--bg-secondary`, `--bg-accent`, `--accent`, `--accent-hover`, `--text-primary`, `--text-secondary`, `--text-muted`, `--disabled`); all hardcoded hex values replaced throughout `<style>` block; prerequisite for future dark/light theme toggle
|
||||
- **Toast notifications** — slide-up toast (bottom-right, 3.5s auto-dismiss, accent border glow) appears on entry save, entry delete, and project note save; error toast shown if a DB call fails
|
||||
- **Keyboard shortcut `N`** — press `N` from anywhere (when not in a text field) to jump focus to the main entry textarea; `Escape` closes the side panel or blurs the active input
|
||||
- **Scanline overlay** — subtle CRT scanline texture via `body::before` repeating gradient; matches terminal aesthetic
|
||||
- **Bug fix: `getKnownProjects()` crash** — function called `.trim()` on `projectId` for all entries including breakout markers, which store `projectId` as a number; fixed by filtering to `type !== 'breakout'` and `typeof projectId === 'string'` before mapping
|
||||
- **Bug fix: `activateGroupFilter()` crash** — same root cause; added `type !== 'breakout'` guard to prevent `.trim()` TypeError on numeric project IDs
|
||||
- **Error handling in panel submit** — added try/catch to `panelSubmit`; previously failed silently on any DB error; now shows error toast and logs to console
|
||||
- **Borrowed from TaskOpi** (`C:\Users\jbrock\Documents\pisyncfolder\taskopi`) — toast pattern, keyboard shortcut pattern, CSS variable architecture, scanline overlay technique
|
||||
|
||||
### v1.8 — April 21, 2026
|
||||
- Added **Project Breakout Panels** — side panel system for project-scoped note-taking alongside the main journal timeline
|
||||
- Bumped IndexedDB to **version 2**; added two new object stores: `projects` (id, name, created) and `project_entries` (id, projectId, text, date, timestamp, mood, tags) with a `projectId` index on `project_entries`
|
||||
- Added **breakout marker** entry type in the existing `entries` store (`type: 'breakout'`); inserted into the main timeline at the selected date to show where a context switch occurred
|
||||
- **Breakout card** renders in the timeline in place of a regular entry — shows project name, live entry count, `open →` button, and a `✕` delete button; card is indented to match timeline flow but uses a card style (no dot/line)
|
||||
- **`+ Project` button** added to the input row (left of word count); opens an inline prompt with datalist autocomplete from existing projects; confirm creates/reuses the project and inserts the breakout marker
|
||||
- **Side panel** slides in from the right when `open →` is clicked; main timeline stays visible alongside it (`flex-direction: row` layout); panel shows project entries grouped by date, newest first
|
||||
- Panel has its own textarea + Add Entry button; Ctrl+Enter also submits; entries are saved to `project_entries` (completely separate from the main journal stream)
|
||||
- `closeProjectPanel()` hides the panel and restores single-column layout
|
||||
- **Safety guards added**: `exportMarkdown` filters out breakout markers (no `text` field); `activateGroupFilter` skips breakout markers to avoid `.trim()` TypeError on numeric `projectId`
|
||||
- New DB helpers: `createProject`, `getAllProjects`, `saveProjectEntry`, `getProjectEntries`, `getProjectEntryCount`, `insertBreakoutMarker`, `deleteBreakoutMarker`
|
||||
|
||||
### v1.7 — April 13, 2026
|
||||
- Added **project ID field** on each entry — optional text input in the new-entry form; saves as `projectId` on the IndexedDB entry object
|
||||
- Added **project badge** (`.entry-site-badge`) on every entry card — displays project name in accent red with a left-border pill style; falls back to `"GENERAL"` when no project is set
|
||||
- Added **smart autocomplete** for the project field — `getKnownProjects()` reads all unique `projectId` values from IndexedDB and populates a native `<datalist>`; suggestions refresh after every save and on page load
|
||||
- **Timeline stays strictly chronological** — all entries sort by timestamp descending regardless of project assignment; project context shown inline via badge rather than separate sections
|
||||
- **Chronological group ordering** — when multiple projects are active in a day, sections sort by the most-recent entry timestamp in each group (not alphabetically), preserving the expected reading order
|
||||
- Added CSS for collapsible project-section headers (`.project-group`, `.project-group-header`, `.project-group-entries`, `.project-group-chevron`) — available for future use if grouped view is desired
|
||||
|
||||
### v1.6 — April 8, 2026
|
||||
- Added **word count display** in the input actions row (between selected date and Add Entry button)
|
||||
- Live counter updates on every keystroke; resets to "0 words" after saving
|
||||
- Singular "1 word" / plural "N words" formatting
|
||||
- Styled with `text-secondary` color (#888888) at 0.75rem
|
||||
|
||||
### v1.5 — April 8, 2026
|
||||
- Added **Jump to Today** button in month nav row (right of `>` arrow)
|
||||
- Resets `currentYear`, `currentMonth`, and `selectedDate` to today; re-renders calendar, timeline, and date display
|
||||
- Subtle ghost style (muted border + text); accent hover on approach
|
||||
|
||||
### v1.4 — April 8, 2026
|
||||
- Added **entry count badge** on calendar days with entries
|
||||
- `getDaysWithEntries()` now returns `Map<day, count>` instead of `Set<day>`
|
||||
- Calendar cells with entries render two-line layout: day number + small count below
|
||||
- Badge is bold, slightly transparent white, 0.6rem — stays within the 36px circle
|
||||
- Days without entries unchanged
|
||||
|
||||
### v1.3 — April 8, 2026
|
||||
- Added **mood/energy tag** selector in input area (😊 😐 😤 😴) — optional per entry
|
||||
- Mood stored as `mood` field on each IndexedDB entry
|
||||
- Selected mood highlights with accent border; click again to deselect (toggle)
|
||||
- Mood clears automatically after each save
|
||||
- Mood emoji shown in entry footer alongside the date
|
||||
- Stats bar shows live mood tally for today (e.g. `😊×2 😴`) — hidden if no moods logged today
|
||||
- Markdown export includes mood emoji inline with timestamp
|
||||
- `saveEntry()` updated with optional `mood = null` parameter
|
||||
|
||||
### v1.2 — April 8, 2026
|
||||
- Added **delete entry** — button appears on hover at end of entry footer; requires confirm before removal
|
||||
- Added **edit entry text** — click "edit" to replace entry text with an inline textarea; Enter saves, Escape cancels, blur saves
|
||||
- Added **time updater** — click any timestamp to open a native time input inline; Enter/blur saves, Escape cancels
|
||||
- Added `deleteEntry(id)` and `updateEntry(id, fields)` IndexedDB helpers
|
||||
- Entry HTML now includes `data-id` and `data-date` attributes for DOM-driven edits
|
||||
- Entry footer restructured: date (left) + action buttons (right, fade in on hover)
|
||||
|
||||
### v1.1 — April 8, 2026
|
||||
- Added stats bar between header and main
|
||||
- Stats: entries today · current streak · peak hour · 30-day activity heatmap
|
||||
- Heatmap uses 4-level intensity scale matching accent color palette
|
||||
- `renderStatsBar()` called on init and after every new entry save
|
||||
|
||||
### v1.0 — April 7, 2026
|
||||
- Initial build
|
||||
- Vertical timeline with connecting line and entry dots
|
||||
- 12-hour timestamp format
|
||||
- Auto-scroll to newest entry
|
||||
- Text input with Ctrl+Enter shortcut
|
||||
- Mini calendar (top-right) with entry day highlighting and click-to-navigate
|
||||
- Month navigation (Prev/Next)
|
||||
- Export current month to Markdown (.md)
|
||||
- IndexedDB persistence
|
||||
|
||||
---
|
||||
|
||||
## Roadmap
|
||||
|
||||
Items are ordered by priority within each tier. Check off as completed.
|
||||
|
||||
### 🔴 High Priority
|
||||
|
||||
- [x] **Stats bar** — Compact strip above the timeline showing: entries today, current streak (consecutive days with ≥1 entry), most active hour, 30-day activity heatmap (GitHub-style)
|
||||
- [x] **Delete entry** — Delete button at end of entry content, subtle styling, confirm step before removal
|
||||
- [x] **Edit entry text** — Click entry text to edit inline; save on blur or Enter
|
||||
- [x] **Time updater** — Click timestamp to edit it inline; maintain 12-hour format
|
||||
- [ ] data storage for notes
|
||||
|
||||
### 🟡 Medium Priority
|
||||
|
||||
- [x] **Entry count badge on calendar days** — Show number of entries per day inside the calendar dot/cell
|
||||
- [x] **Mood/energy tag** — Optional tag per entry (😊 😐 😤 😴); stored with entry; shown in stats over time
|
||||
- [x] **Jump to Today button** — One-click return to today's date from any month view
|
||||
- [ ] **Date range export** — Replace current "export this month" with a date picker (from / to) so the user can export any span of days; UI appears as a small inline form triggered from the export button
|
||||
- [x] **Word count display** — Live counter in the input area while writing
|
||||
- [x] **Project breakout panels** — Insert a breakout card into the main timeline that links to a separate project timeline in a side panel; project entries are independent from the main journal *(Implemented v1.8)*
|
||||
|
||||
### 🟢 Low Priority
|
||||
|
||||
- [ ] **Delete project notes** — Delete button on individual entries inside the project side panel; requires `deleteProjectEntry(id)` DB helper on `project_entries` store and re-render of panel timeline + breakout card count
|
||||
- [x] **Project card timeline connector** — Visual line extending from the breakout card's left edge to the main timeline vertical line; implemented via `::before`/`::after` pseudo-elements on `.breakout-card` *(v1.10)*
|
||||
- [ ] Follow-up: breakout dot still slightly off-center on the timeline — needs positional tweak
|
||||
|
||||
- [x] **Project grouping within timeline** — Project badge on each entry card; timeline stays chronological; autocomplete from prior project names; collapsible section CSS ready for future grouped view
|
||||
- [ ] **Dark/Light theme toggle** — User preference stored in localStorage
|
||||
- [ ] **Pinned/starred entries** — Star an entry to surface it at top of day or in a favorites view
|
||||
- [ ] **Markdown preview** — Toggle between raw and rendered markdown in entry view
|
||||
- [ ] **Keyboard navigation** — Navigate entries with arrow keys
|
||||
- [ ] **Backup/Restore** — Export/import entire IndexedDB as JSON
|
||||
|
||||
---
|
||||
# Future update Ideas
|
||||
1. Multi team - Groups can work on the same time line for the same day projects.
|
||||
1. Time line would show the name of the person who input an entry into the timeline
|
||||
2.
|
||||
|
||||
---
|
||||
|
||||
## Design Constraints (Do Not Change)
|
||||
|
||||
These values are calibrated to prevent visual overlap between the timeline line, dot, and timestamp text.
|
||||
|
||||
| Element | Property | Value |
|
||||
|---------|----------|-------|
|
||||
| Timeline padding-left | `padding-left` | `120px` |
|
||||
| Timeline line position | `left` | `50px` |
|
||||
| Entry dot position | `left` | `-75px` |
|
||||
| Entry time position | `left` | `-105px` |
|
||||
| Entry time width | `width` | `95px` |
|
||||
| Entry time text-align | `text-align` | `right` |
|
||||
|
||||
**Note on new UI elements:** Delete buttons belong at the end of `.entry-content`, small and muted. Edit controls should appear inline without breaking the dot/line layout.
|
||||
|
||||
---
|
||||
|
||||
## Color Profile
|
||||
|
||||
| Token | Hex | Usage |
|
||||
|-------|-----|-------|
|
||||
| `bg-primary` | `#1a1a2e` | Body background |
|
||||
| `bg-secondary` | `#16213e` | Header, entry cards, input section |
|
||||
| `bg-accent` | `#0f3460` | Timeline line, borders, inactive states |
|
||||
| `accent` | `#e94560` | Dots, buttons, highlights, selected states |
|
||||
| `accent-hover` | `#ff6b6b` | Button hover |
|
||||
| `text-primary` | `#eaeaea` | Main text |
|
||||
| `text-secondary` | `#888888` | Timestamps, labels |
|
||||
| `text-muted` | `#666666` | Empty state, entry dates |
|
||||
| `disabled` | `#444444` | Disabled button backgrounds |
|
||||
|
||||
---
|
||||
|
||||
## Layout
|
||||
|
||||
# This area needs to be updated
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ [Stats Bar: streak · entries today · heatmap] │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ [Mini Calendar] [Export Button] │
|
||||
│ [◄ Month ►] │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 10:30 AM │ ● Entry 3 [edit][del] │
|
||||
│ │ │
|
||||
│ 8:15 AM │ ● Entry 2 [edit][del] │
|
||||
│ │ │
|
||||
│ 7:00 AM │ ● Entry 1 [edit][del] │
|
||||
│ │ │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ [Text Input Area] [word count] │
|
||||
│ [Selected Date] [Add Entry ▶] │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dev Notes
|
||||
|
||||
- All CSS lives in the `<style>` block; all JS in the `<script>` block at the bottom — keep it that way
|
||||
- To reset data: DevTools (F12) → Application → IndexedDB → Delete `JournalDB`
|
||||
- Works in any modern browser with no build step
|
||||
- IndexedDB is per-origin — the file needs to be served from the same path to retain data
|
||||
|
||||
### Future Storage Options (if needed)
|
||||
- **SQLite-WASM** — runs in-browser, more robust querying
|
||||
- **Electron wrapper** — native app feel, access to filesystem
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
Journal App/
|
||||
├── journal.html # The complete application
|
||||
└── MASTER_PROJECT_LOG.md # This file
|
||||
```
|
||||
|
||||
---
|
||||
## Noted updates
|
||||
4/8/2026
|
||||
All changes are complete. Here's what was added:
|
||||
|
||||
**New features:**
|
||||
|
||||
- **Tag input** in the new-entry form (between mood and textarea) — type a tag and press `Enter` or `,` to add it; `Backspace` removes the last tag; comma-separated pastes work too
|
||||
- **Tag chips on entry cards** — saved tags display as `#tagname` pills; clicking one activates the tag filter
|
||||
- **Tag filter view** — clicking any tag chip shows all entries with that tag across all dates, grouped by date, with a "Filtered by: #tag [✕ Clear]" bar at the top
|
||||
- **Inline tag editing** — a "tags" button on each card opens the tag input widget inline; focus-away saves and reverts to chips
|
||||
- **Markdown export** — tags are appended as `#tagname` at the end of each exported entry line
|
||||
|
||||
**Backward compatible** — existing entries without tags render cleanly with no errors.
|
||||
|
||||
---
|
||||
|
||||
## Project Breakout Panels (Future Feature — Fully Planned)
|
||||
|
||||
**Goal:** Insert a breakout card into the main timeline that links to a separate project timeline displayed in a slide-in side panel. Project entries are completely independent from the main journal.
|
||||
|
||||
**Motivation:** When switching between multiple tasks/projects during a workday, users need a way to context-switch cleanly — keeping project notes separate from general journal entries, while still seeing where the switch happened in the main timeline.
|
||||
|
||||
### User Decisions (Finalized)
|
||||
- **Panel style:** Side panel — slides in from the right, main timeline stays visible alongside it
|
||||
- **Entry ownership:** Project-only — entries added in the panel do not appear in the main day timeline
|
||||
- **Insert trigger:** Manual — a "+" button in the input area; user names the project at that moment
|
||||
|
||||
### Visual Layout
|
||||
```
|
||||
┌──────────────────────┬─────────────────────────────┐
|
||||
│ Main Timeline │ 🔗 BOM Project [✕]│
|
||||
│ ───────────────── ├─────────────────────────────┤
|
||||
│ 4:24 PM ● [entry] │ 4:24 PM ● Last BOM page │
|
||||
│ │ 3:09 PM ● Updating parts │
|
||||
│ ┌──────────────────┐ │ │
|
||||
│ │ 🔗 BOM Project │ │ ┌─────────────────────────┐ │
|
||||
│ │ 3 entries [open→]│─┼▶│ Add note to project... │ │
|
||||
│ └──────────────────┘ │ └─────────────────────────┘ │
|
||||
│ │ [ Add Entry ] │
|
||||
│ 3:09 PM ● [entry] │ │
|
||||
└──────────────────────┴─────────────────────────────┘
|
||||
```
|
||||
|
||||
### Data Model
|
||||
Requires IndexedDB **version bump from 1 → 2**, adding two new object stores:
|
||||
|
||||
```javascript
|
||||
// 'projects' store
|
||||
{ id: number (auto), name: string, created: string (ISO) }
|
||||
|
||||
// 'project_entries' store (index on projectId)
|
||||
{ id: number (auto), projectId: number, text: string,
|
||||
date: string, timestamp: number, mood: string|null, tags: string[] }
|
||||
|
||||
// Breakout markers — stored in existing 'entries' store as a special type:
|
||||
{ type: 'breakout', projectId: number, projectName: string, date, timestamp, id }
|
||||
```
|
||||
|
||||
### New DB Functions Needed
|
||||
- `createProject(name)` → Promise\<id\>
|
||||
- `getAllProjects()` → Promise\<project[]\>
|
||||
- `saveProjectEntry(projectId, text, date, mood, tags)` → Promise\<id\>
|
||||
- `getProjectEntries(projectId)` → Promise\<entry[]\> sorted desc by timestamp
|
||||
- `getProjectEntryCount(projectId)` → Promise\<number\>
|
||||
- `insertBreakoutMarker(projectId, projectName, date)` → saves to `entries` store
|
||||
- `deleteBreakoutMarker(id)` → deletes from `entries` store
|
||||
|
||||
### New State Variables
|
||||
```javascript
|
||||
let activePanelProjectId = null; // number | null
|
||||
let existingProjects = []; // cache for autocomplete
|
||||
```
|
||||
|
||||
### HTML Changes
|
||||
1. Wrap `timeline-container` + `input-section` in `<div class="main-col">` inside `<main>`
|
||||
2. Add `<div id="sidePanel" class="side-panel" style="display:none">` as sibling in `<main>`
|
||||
- Contains: header (title + ✕ close), scrollable timeline div, input area (textarea + Add Entry)
|
||||
3. Add `<button id="insertBreakoutBtn" class="project-break-btn">+ Project</button>` in `input-actions`
|
||||
|
||||
### renderTimeline() Changes
|
||||
- Detect `entry.type === 'breakout'` in the map — render a breakout card instead of a regular entry
|
||||
- Breakout card shows: project name, entry count (loaded async), "open →" button, ✕ delete button
|
||||
- Add event listeners: open panel on "open →" click; delete marker on ✕ click
|
||||
|
||||
### New Functions
|
||||
- `openProjectPanel(projectId, projectName)` — shows panel, sets title, calls `renderProjectTimeline()`
|
||||
- `closeProjectPanel()` — hides panel, removes `main--panel-open` class
|
||||
- `renderProjectTimeline(projectId)` — loads project entries, renders them in panel (grouped by date)
|
||||
- `showBreakoutPrompt(projects)` — inline name input with autocomplete; on confirm creates/reuses project and inserts breakout marker
|
||||
|
||||
### CSS Changes
|
||||
- `main.main--panel-open { flex-direction: row; }` — switches main from column to row layout
|
||||
- `.main-col { flex: 1; display: flex; flex-direction: column; overflow: hidden; }` — wraps current content
|
||||
- `.side-panel { width: 360px; flex-shrink: 0; }` — fixed width panel with slide-in animation
|
||||
- `.breakout-card` — styled differently from regular entries; accent left border, card-style with "open →" button
|
||||
- `.project-break-btn` — dashed ghost button in input-actions area
|
||||
|
||||
### Implementation Order
|
||||
1. Bump `DB_VERSION` to 2; add `projects` and `project_entries` stores in `onupgradeneeded`
|
||||
2. Add all new DB helper functions
|
||||
3. Add new state variables
|
||||
4. Update HTML: add `.main-col` wrapper, `#sidePanel`, `#insertBreakoutBtn`
|
||||
5. Modify `renderTimeline()` to handle `type === 'breakout'` cards
|
||||
6. Add `openProjectPanel()`, `closeProjectPanel()`, `renderProjectTimeline()`
|
||||
7. Add `showBreakoutPrompt()` and confirm handler
|
||||
8. Wire up panel submit handler and close button in `init()`
|
||||
9. Add all CSS
|
||||
|
||||
---
|
||||
|
||||
## Project Grouping Design (Earlier Exploration — Superseded)
|
||||
|
||||
*The breakout panel approach above was chosen over this option. Kept for reference.*
|
||||
|
||||
**Original concept:** Add a `project` field to each regular entry, then group entries by project within the day timeline using section headers. Clicking a header shows a cross-date filtered view for that project.
|
||||
|
||||
**Why not chosen:** The breakout panel approach is cleaner — project notes stay completely separate from the journal stream, and the side-by-side panel feels more natural for context-switching between tasks.
|
||||
|
After Width: | Height: | Size: 141 KiB |