[READ-ONLY] Mirror of https://github.com/probablykasper/mr-tagger. Music file tagging app for Mac, Linux and Windows
audio linux macos music tagger tauri windows
0

Configure Feed

Select the types of activity you want to include in your feed.

Show title

Kasper (Aug 27, 2021, 2:02 AM +0200) 33c0da47 24ea6624

+112 -57
+13 -12
src-tauri/src/cmd.rs
··· 1 - use crate::frames::{get_frames, Frame, Metadata}; 1 + use crate::frames::{get_frames, Metadata}; 2 2 use crate::throw; 3 3 use serde::Serialize; 4 4 use serde_json::Value; ··· 57 57 app.current_index = index; 58 58 } 59 59 60 - #[derive(Serialize)] 61 - pub struct Page { 62 - path: PathBuf, 63 - frames: Vec<Frame>, 64 - } 65 - 66 60 #[command] 67 - pub fn get_page(app: AppArg<'_>) -> Option<Page> { 61 + pub fn get_page(app: AppArg<'_>) -> Option<Value> { 68 62 let mut app = app.0.lock().unwrap(); 69 63 let file = app.current_file().ok()?; 70 - Some(Page { 71 - path: file.path.clone(), 72 - frames: get_frames(&file.metadata), 73 - }) 64 + 65 + let title = match file.metadata { 66 + Metadata::Id3(ref tag) => tag.title(), 67 + Metadata::Mp4(ref tag) => tag.title(), 68 + }; 69 + 70 + Some(serde_json::json!({ 71 + "path": file.path.clone(), 72 + "title": title, 73 + "frames": get_frames(&file.metadata), 74 + })) 74 75 }
+1 -5
src-tauri/src/main.rs
··· 101 101 .inner_size(800.0, 550.0) 102 102 .min_inner_size(400.0, 200.0) 103 103 .skip_taskbar(false) 104 - .fullscreen(false) 105 - .visible(false); 104 + .fullscreen(false); 106 105 return (win, webview); 107 - }) 108 - .on_page_load(|w, _payload| { 109 - w.show().unwrap(); 110 106 }) 111 107 .manage(cmd::AppState(Default::default())) 112 108 .menu(menu)
+24 -20
src/App.svelte
··· 1 1 <script lang="ts"> 2 2 import { dialog, event } from '@tauri-apps/api' 3 3 import { checkShortcut, runCmd } from './scripts/helpers' 4 - import PageView from './components/Item.svelte' 5 - import type { Page } from './components/Item.svelte' 4 + import PageView from './components/Page.svelte' 5 + import type { Page } from './components/Page.svelte' 6 6 import FileDrop from './components/FileDrop.svelte' 7 7 import { onDestroy } from 'svelte' 8 + import { fade } from 'svelte/transition' 8 9 9 10 type File = { 10 11 path: string ··· 106 107 <div class="files" tabindex="0" on:keydown={filesKeydown}> 107 108 {#each app.files as file, i} 108 109 <div class="file" class:selected={i === app.current_index} on:click={() => show(i)}> 109 - <div class="icon x" on:click|stopPropagation={() => close(i)}> 110 - <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" 111 - ><path 112 - d="M23.954 21.03l-9.184-9.095 9.092-9.174-2.832-2.807-9.09 9.179-9.176-9.088-2.81 2.81 9.186 9.105-9.095 9.184 2.81 2.81 9.112-9.192 9.18 9.1z" /></svg> 113 - </div> 114 110 <div class="icon dirty"> 115 111 {#if file.dirty} 116 112 <svg width="6" height="6" xmlns="http://www.w3.org/2000/svg"> ··· 118 114 </svg> 119 115 {/if} 120 116 </div> 117 + <div class="icon x" on:click|stopPropagation={() => close(i)}> 118 + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" 119 + ><path 120 + d="M23.954 21.03l-9.184-9.095 9.092-9.174-2.832-2.807-9.09 9.179-9.176-9.088-2.81 2.81 9.186 9.105-9.095 9.184 2.81 2.81 9.112-9.192 9.18 9.1z" /></svg> 121 + </div> 121 122 {file.path.replace(/^.*[\\\/]/, '')} 122 123 </div> 123 124 {/each} ··· 126 127 </div> 127 128 <div class="main"> 128 129 {#if page} 129 - <button on:click={() => saveFile(false)}>Save</button> 130 - <PageView item={page} on:appRefresh={getApp} /> 130 + <button on:click={() => saveFile(false)} tabindex="0">Save</button> 131 + <PageView {page} on:appRefresh={getApp} /> 131 132 {/if} 132 133 </div> 133 134 </main> ··· 150 151 width: 0px 151 152 overflow: auto 152 153 .sidebar 153 - position: relative 154 154 display: flex 155 155 flex-direction: column 156 156 width: 250px ··· 168 168 .file 169 169 display: flex 170 170 align-items: center 171 - padding: 7px 8px 171 + padding: 6px 8px 172 172 padding-left: 0px 173 173 cursor: default 174 174 .icon ··· 179 179 height: 8px 180 180 flex-shrink: 0 181 181 padding: 3px 182 - margin-right: 3px 183 - margin-left: 5px 182 + margin: 0px 5px 184 183 border-radius: 2px 184 + transition: opacity 100ms ease-out, transform 100ms ease-out 185 185 &:hover 186 186 background-color: rgba(#ffffff, 0.15) 187 - .x 188 - display: none 189 - &:hover .x 187 + .icon.x 188 + opacity: 0 189 + transform: scale(0.5) 190 + position: absolute 191 + &:hover .icon.x 190 192 display: flex 191 - &:hover .dirty 192 - display: none 193 + opacity: 1 194 + transform: scale(1) 195 + &:hover .icon.dirty 196 + opacity: 0 197 + transform: scale(0.5) 193 198 svg 194 199 fill: #ffffff 195 - // width: 6px 196 - // height: 6px 197 200 .file:nth-child(2n) 198 201 background-color: rgba(#ffffff, 0.05) 199 202 .file.selected 200 203 background-color: hsl(147, 0%, 35%) 201 204 &:focus .file.selected 202 205 background-color: hsl(147, 70%, 30%) 206 + background-color: #103fcb 203 207 </style>
+74 -20
src/components/Item.svelte src/components/Page.svelte
··· 12 12 } 13 13 export type Page = { 14 14 path: string 15 + title: string 15 16 frames: Frame[] 16 17 } 17 18 let x = 0 // to fix syntax highlighting ··· 23 24 import { dialog } from '@tauri-apps/api' 24 25 import FileDrop from './FileDrop.svelte' 25 26 26 - export let item: Page 27 + export let page: Page 27 28 28 29 let image: Image | null = null 29 - $: if (item) { 30 + $: if (page) { 30 31 image = null 31 32 getImage(null) 32 33 } ··· 60 61 } 61 62 dispatch('appRefresh') 62 63 } 64 + let showFrames = true 63 65 let svgWidth = 0 64 66 </script> 65 67 ··· 86 88 <button on:click={removeImage}>Remove</button> 87 89 <button on:click={() => setImage()}>Replace</button> 88 90 </div> 89 - <div>{image.index + 1} of {image.total_images}</div> 90 - <div>{image.mime_type}</div> 91 + <div class="text">{image.index + 1} of {image.total_images}</div> 92 + <div class="text">{image.mime_type}</div> 91 93 {#if image.picture_type} 92 - <div>Type: {image.picture_type}</div> 94 + <div class="text">Type: {image.picture_type}</div> 93 95 {/if} 94 96 {#if image.description} 95 - <div>Description: {image.description}</div> 97 + <div class="text">Description: {image.description}</div> 96 98 {/if} 97 99 {:else} 98 100 <div> ··· 101 103 {/if} 102 104 </div> 103 105 <div class="right"> 104 - <div>{item.path}</div> 105 - {#each item.frames as frame} 106 - <div class="item"> 107 - {#if frame.Text} 108 - <p>{frame.Text.id}: {frame.Text.value}</p> 109 - {/if} 110 - </div> 111 - {/each} 106 + <div class="row"> 107 + <span class="label">Path</span> 108 + <span class="content">{page.path}</span> 109 + </div> 110 + <div class="row"> 111 + <span class="label">Title</span> 112 + <span class="content">{page.title}</span> 113 + </div> 114 + <button class="toggle" tabindex="0" on:click={() => (showFrames = !showFrames)} 115 + >{showFrames ? 'Hide tags' : 'Show tags'}</button> 116 + <div class="frames"> 117 + {#if showFrames} 118 + {#each page.frames as frame} 119 + {#if frame.Text} 120 + <div class="frame-label">{frame.Text.id}</div> 121 + <div class="content">{frame.Text.value}</div> 122 + {/if} 123 + {/each} 124 + {/if} 125 + </div> 112 126 </div> 113 127 </main> 114 128 115 129 <style lang="sass"> 116 130 main 117 131 display: flex 118 - margin: 12px 119 - font-size: 14px 132 + font-size: 13px 133 + padding-bottom: 12px 134 + padding-right: 12px 135 + .text 136 + user-select: auto 137 + -webkit-user-select: auto 120 138 .left 121 - margin-right: 12px 122 139 min-width: 160px 123 140 width: calc(50% - 160px) 124 141 max-width: 250px 125 - .right 126 - width: 0px 127 - flex-grow: 1 142 + padding-left: 12px 128 143 img 129 144 display: block 130 145 width: 100% ··· 139 154 svg 140 155 box-sizing: border-box 141 156 fill: #45464a 157 + .right 158 + width: 0px 159 + flex-grow: 1 160 + .row 161 + padding: 5px 0px 162 + display: flex 163 + align-items: baseline 164 + .label 165 + display: inline-block 166 + width: 76px 167 + flex-shrink: 0 168 + text-align: right 169 + margin-right: 8px 170 + font-size: 12px 171 + opacity: 0.7 172 + cursor: default 173 + .content 174 + font-size: 13px 175 + user-select: auto 176 + -webkit-user-select: auto 177 + button.toggle 178 + font-size: 12px 179 + background: transparent 180 + padding-left: 0px 181 + margin: 0px 182 + margin-left: 20px 183 + border: none 184 + color: #3366ff 185 + &:active 186 + opacity: 0.8 187 + .frames 188 + padding-left: 20px 189 + user-select: auto 190 + -webkit-user-select: auto 191 + .frame-label 192 + font-size: 12px 193 + opacity: 0.7 194 + padding-top: 8px 195 + // padding-bottom: 2px 142 196 </style>