@@ -57,9 +57,14 @@ struct ContentView: View {
5757 }
5858 // iPhone UX: Einfügemarke + Inspector einklappen beim Einfügen.
5959 @ State private var insertTarget : DiagramInsertTarget ? = nil
60- @ State private var hideInspectorOnPhone : Bool = false
60+ /// iPhone: Inspector startet eingeklappt, damit das Diagramm Platz hat.
61+ @ State private var hideInspectorOnPhone : Bool = true
6162 // iPhone UX: Palette automatisch einklappen beim Text-Editieren.
62- @ State private var showPaletteOnPhone : Bool = true
63+ /// iPhone: Palette als Sheet über dem Editor (statt fest über der Navigationsleiste).
64+ @ State private var showPaletteOnPhone : Bool = false
65+ /// iPhone: Diagrammtitel wird in einem kleinen Dialog bearbeitet statt in einem eigenen Feld über dem Diagramm.
66+ @ State private var showPhoneTitleEditor : Bool = false
67+ @ State private var phoneTitleDraft : String = " "
6368 // In-App Zwischenablage für Diagramm-Elemente (Copy/Cut/Paste).
6469 @ State private var elementClipboard : VisuStructElement ? = nil
6570 #if canImport( UIKit )
@@ -177,7 +182,7 @@ struct ContentView: View {
177182 . navigationSplitViewStyle ( . balanced )
178183 } else {
179184 VStack ( spacing : 0 ) {
180- if ! isPhone || showPaletteOnPhone {
185+ if ! isPhone {
181186 paletteListPanel
182187 . frame ( maxHeight : 300 , alignment : . top )
183188 . background ( Color ( . secondarySystemGroupedBackground ) )
@@ -187,6 +192,14 @@ struct ContentView: View {
187192 mainEditorNavigationStack
188193 . frame ( maxWidth : . infinity , maxHeight : . infinity )
189194 }
195+ . sheet ( isPresented : phonePaletteSheetBinding ) {
196+ paletteListPanel
197+ . environment ( \. appLanguage , lang )
198+ . presentationDetents ( [ . medium , . large ] )
199+ // Diagramm bleibt bedienbar, z. B. um eine Einfügestelle zu wählen.
200+ . presentationBackgroundInteraction ( . enabled ( upThrough : . medium ) )
201+ . presentationDragIndicator ( . visible )
202+ }
190203 }
191204 }
192205 #if canImport( UIKit )
@@ -346,6 +359,11 @@ struct ContentView: View {
346359 refreshLineEditor ( )
347360 DiagramCommandCenter . shared . update ( file : diagramFileActions , edit : diagramEditActions )
348361 }
362+ . onChange ( of : insertTarget ) { _ , newTarget in
363+ // iPhone: Einfügestelle gewählt → Palette öffnen, damit gleich ein Element gewählt werden kann.
364+ guard isPhone , newTarget != nil else { return }
365+ showPaletteOnPhone = true
366+ }
349367 . onChange ( of : focusedField ) { _ , newVal in
350368 // iPhone: Sobald Textbearbeitung startet, Palette einklappen für mehr Platz.
351369 guard isPhone else { return }
@@ -881,21 +899,25 @@ struct ContentView: View {
881899 let blockCorner : CGFloat = horizontalSizeClass == . regular ? 14 : 12
882900
883901 return VStack ( alignment : . leading , spacing : 0 ) {
884- VStack ( alignment : . leading , spacing : 8 ) {
885- Text ( lang . tr ( " diagram_title_label " ) )
886- . font ( horizontalSizeClass == . regular ? . caption : . subheadline )
887- . foregroundStyle ( . secondary )
888- TextField ( lang . tr ( " diagram_title_placeholder " ) , text : captionBinding )
889- . font ( horizontalSizeClass == . regular ? . subheadline : . body )
890- . textFieldStyle ( . roundedBorder )
891- . textInputAutocapitalization ( . never )
892- . autocorrectionDisabled ( true )
893- . focused ( $focusedField , equals : . caption )
902+ if isPhone {
903+ phoneCaptionRow
904+ } else {
905+ VStack ( alignment : . leading , spacing : 8 ) {
906+ Text ( lang . tr ( " diagram_title_label " ) )
907+ . font ( horizontalSizeClass == . regular ? . caption : . subheadline )
908+ . foregroundStyle ( . secondary )
909+ TextField ( lang . tr ( " diagram_title_placeholder " ) , text : captionBinding )
910+ . font ( horizontalSizeClass == . regular ? . subheadline : . body )
911+ . textFieldStyle ( . roundedBorder )
912+ . textInputAutocapitalization ( . never )
913+ . autocorrectionDisabled ( true )
914+ . focused ( $focusedField , equals : . caption )
915+ }
916+ . frame ( maxWidth : . infinity , alignment : . leading )
917+ . padding ( . horizontal , 14 )
918+ . padding ( . top , 8 )
919+ . padding ( . bottom , 6 )
894920 }
895- . frame ( maxWidth : . infinity , alignment : . leading )
896- . padding ( . horizontal , 14 )
897- . padding ( . top , 8 )
898- . padding ( . bottom , 6 )
899921 // Innerer Trennstrich — Titel zählt zum Diagramm-„Blatt“, nicht als losgelöster Bereich oberhalb.
900922 Rectangle ( )
901923 . fill ( Color . primary . opacity ( 0.1 ) )
@@ -935,6 +957,47 @@ struct ContentView: View {
935957 }
936958 }
937959
960+ /// iPhone: Titel als eine kompakte Zeile; Tippen öffnet einen Dialog zum Bearbeiten.
961+ private var phoneCaptionRow : some View {
962+ Button {
963+ phoneTitleDraft = document . caption
964+ showPhoneTitleEditor = true
965+ } label : {
966+ HStack ( spacing : 6 ) {
967+ Text ( document . caption . isEmpty ? lang . tr ( " diagram_title_placeholder " ) : document . caption )
968+ . font ( . subheadline . weight ( . semibold ) )
969+ . foregroundStyle ( document . caption . isEmpty ? . secondary : . primary )
970+ . lineLimit ( 1 )
971+ Image ( systemName : " pencil " )
972+ . font ( . caption )
973+ . foregroundStyle ( . secondary )
974+ }
975+ . frame ( maxWidth : . infinity , alignment : . leading )
976+ . contentShape ( Rectangle ( ) )
977+ }
978+ . buttonStyle ( . plain )
979+ . accessibilityLabel ( lang . tr ( " diagram_title_label " ) )
980+ . padding ( . horizontal , 14 )
981+ . padding ( . vertical , 8 )
982+ . alert ( lang . tr ( " diagram_title_label " ) , isPresented : $showPhoneTitleEditor ) {
983+ TextField ( lang . tr ( " diagram_title_placeholder " ) , text : $phoneTitleDraft )
984+ . textInputAutocapitalization ( . never )
985+ . autocorrectionDisabled ( true )
986+ Button ( lang . tr ( " phone_title_done " ) ) {
987+ if phoneTitleDraft != document . caption {
988+ captionBinding . wrappedValue = phoneTitleDraft
989+ }
990+ }
991+ }
992+ }
993+
994+ private var phonePaletteSheetBinding : Binding < Bool > {
995+ Binding (
996+ get : { isPhone && showPaletteOnPhone } ,
997+ set : { showPaletteOnPhone = $0 }
998+ )
999+ }
1000+
9381001 // MARK: - Bindings (Dokument, Caption)
9391002
9401003 private var documentBinding : Binding < VisuStructDocument > {
@@ -1494,7 +1557,11 @@ struct ContentView: View {
14941557 insertTargetActive : insertTarget != nil ,
14951558 hideInspectorOnPhone : hideInspectorOnPhone ,
14961559 onCancelInsert : { insertTarget = nil } ,
1497- onShowInspector : { hideInspectorOnPhone = false }
1560+ onShowInspector : { hideInspectorOnPhone = false } ,
1561+ onHideInspector : {
1562+ focusedField = nil
1563+ hideInspectorOnPhone = true
1564+ }
14981565 ) {
14991566 inspectorPanel
15001567 }
@@ -1845,6 +1912,7 @@ struct ContentView: View {
18451912 private func insertPaletteItem ( _ item : ElementPalette . PaletteItem ) {
18461913 if isPhone {
18471914 hideInspectorOnPhone = true
1915+ showPaletteOnPhone = false
18481916 }
18491917 let el = ElementPalette . element ( for : item , lang : lang )
18501918 let doc = document
0 commit comments