Skip to content

Commit

Permalink
Scroll to verse when orientation changes (#643)
Browse files Browse the repository at this point in the history
  • Loading branch information
mohamede1945 authored Aug 4, 2024
1 parent 6a786a2 commit 775a63e
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 49 deletions.
48 changes: 23 additions & 25 deletions Features/QuranImageFeature/ContentImageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import NoorUI
import QuranGeometry
import QuranKit
import SwiftUI

struct ContentImageView: View {
Expand All @@ -20,7 +21,8 @@ struct ContentImageView: View {
quarterName: viewModel.page.localizedQuarterName,
suraNames: viewModel.page.suraNames(),
page: viewModel.page.localizedNumber,
scrollToItem: viewModel.scrollToItem,
scrollToVerse: viewModel.scrollToVerse,
wordFrames: viewModel.imagePage?.wordFrames,
onScaleChange: { viewModel.scale = $0 },
onGlobalFrameChange: { viewModel.imageFrame = $0 }
)
Expand All @@ -37,33 +39,28 @@ private struct ContentImageViewBody: View {
let quarterName: String
let suraNames: MultipartText
let page: String
let scrollToItem: WordFrameLine?
let scrollToVerse: AyahNumber?
let wordFrames: WordFrameCollection?
let onScaleChange: (WordFrameScale) -> Void
let onGlobalFrameChange: (CGRect) -> Void

var body: some View {
ScrollViewReader { scrollView in
AdaptiveImageScrollView(decorations: decorations) {
image
} onScaleChange: {
onScaleChange($0)
} onGlobalFrameChange: {
onGlobalFrameChange($0)
} header: {
QuranPageHeader(quarterName: quarterName, suraNames: suraNames)
} footer: {
QuranPageFooter(page: page)
}
// TODO: Should be part of the headers and footers.
.font(.footnote)
.populateReadableInsets()
.onChange(of: scrollToItem) { scrollToItem in
if let scrollToItem {
withAnimation {
scrollView.scrollTo(scrollToItem, anchor: UnitPoint(x: 0, y: 0.2))
}
}
}
AdaptiveImageScrollView(decorations: decorations) {
image
} onScaleChange: {
onScaleChange($0)
} onGlobalFrameChange: {
onGlobalFrameChange($0)
} header: {
QuranPageHeader(quarterName: quarterName, suraNames: suraNames)
} footer: {
QuranPageFooter(page: page)
}
// TODO: Should be part of the headers and footers.
.font(.footnote)
.populateReadableInsets()
.quranScrolling(scrollToValue: scrollToVerse) {
wordFrames?.lineFramesVerVerse($0).first
}
}
}
Expand All @@ -80,7 +77,8 @@ private struct ContentImageViewBody: View {
quarterName: "ABC",
suraNames: "ABC",
page: "604",
scrollToItem: nil,
scrollToVerse: nil,
wordFrames: nil,
onScaleChange: { _ in },
onGlobalFrameChange: { _ in }
)
Expand Down
8 changes: 3 additions & 5 deletions Features/QuranImageFeature/ContentImageViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class ContentImageViewModel: ObservableObject {
@Published var suraHeaderLocations: [SuraHeaderLocation] = []
@Published var ayahNumberLocations: [AyahNumberLocation] = []
@Published var highlights: QuranHighlights
@Published var scrollToItem: WordFrameLine?
@Published var scrollToVerse: AyahNumber?

@Published var scale: WordFrameScale = .zero
@Published var imageFrame: CGRect = .zero
Expand Down Expand Up @@ -108,10 +108,8 @@ class ContentImageViewModel: ObservableObject {
guard let ayah = highlightsService.highlights.firstScrollingVerse() else {
return
}
if let line = imagePage?.wordFrames.lineFramesVerVerse(ayah).first {
logger.info("Quran Image: scrollToVerseIfNeeded \(ayah) - \(line.frames)")
scrollToItem = line
}
logger.info("Quran Image: scrollToVerseIfNeeded \(ayah)")
scrollToVerse = ayah
}

private func scrollToVerseIfNeeded() {
Expand Down
28 changes: 10 additions & 18 deletions Features/QuranTranslationFeature/ContentTranslationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,25 +50,17 @@ private struct ContentTranslationViewBody: View {
let openURL: (TranslationURL) -> Void

var body: some View {
ScrollViewReader { scrollView in
List {
ForEach(items) { item in
item
}
}
.listStyle(.plain)
.environment(\.defaultMinListRowHeight, 1)
.populateReadableInsets()
.openTranslationURL(openURL)
.trackCollection(with: tracker)
.sheet(item: $footnote) { $0 }
.onChange(of: scrollToItem) { scrollToItem in
if let scrollToItem {
withAnimation {
scrollView.scrollTo(scrollToItem, anchor: UnitPoint(x: 0.2, y: 0.2))
}
}
List {
ForEach(items) { item in
item
}
}
.listStyle(.plain)
.environment(\.defaultMinListRowHeight, 1)
.populateReadableInsets()
.openTranslationURL(openURL)
.trackCollection(with: tracker)
.sheet(item: $footnote) { $0 }
.quranScrolling(scrollToValue: scrollToItem)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@
// Copyright © 2019 Quran.com. All rights reserved.
//

import QuranGeometry
import QuranKit
import UIKit

public struct ImagePage: Equatable {
public let image: UIImage
public let wordFrames: WordFrameCollection
public let startAyah: AyahNumber

public init(image: UIImage, wordFrames: WordFrameCollection, startAyah: AyahNumber) {
self.image = image
self.wordFrames = wordFrames
self.startAyah = startAyah
}
}
45 changes: 45 additions & 0 deletions UI/NoorUI/Features/Quran/QuranScrollingViewModifier.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// QuranScrollingViewModifier.swift
//
//
// Created by Mohamed Afifi on 2024-08-03.
//

import SwiftUI

struct QuranScrollingViewModifier<Value: Equatable, ID: Hashable>: ViewModifier {
let scrollToValue: Value?
let transform: (Value) -> ID?
@State private var scrollToValueRequest: Value?

func body(content: Content) -> some View {
ScrollViewReader { scrollView in
content
.onChange(of: scrollToValue) { scrollToValueRequest = $0 }
.onChange(of: scrollToValueRequest) { scrollToValue in
if let scrollToValue, let id = transform(scrollToValue) {
withAnimation {
scrollView.scrollTo(id, anchor: UnitPoint(x: 0, y: 0.2))
}
scrollToValueRequest = nil
}
}
}
.onSizeChange { _ in
scrollToValueRequest = scrollToValue
}
}
}

extension View {
public func quranScrolling<Value: Equatable>(
scrollToValue: Value?,
transform: @escaping (Value) -> (some Hashable)?
) -> some View {
modifier(QuranScrollingViewModifier(scrollToValue: scrollToValue, transform: transform))
}

public func quranScrolling(scrollToValue: (some Hashable)?) -> some View {
modifier(QuranScrollingViewModifier(scrollToValue: scrollToValue) { $0 })
}
}

0 comments on commit 775a63e

Please sign in to comment.