From b81d2a33b62bc2cb009f0a9c3bce960817dd18cf Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 2 Jan 2024 12:57:10 +0800 Subject: [PATCH 1/5] Fix the add RSS/Atom feed link on empty following view --- .../Sources/App/Views/Home/HomeFeedViewIOS.swift | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift index 7814e5ad8..c21248456 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift @@ -143,7 +143,6 @@ struct AnimatingCellHeight: AnimatableModifier { @State var hasHighlightMutations = false @State var searchPresented = false @State var showAddLinkView = false - @State var showAddFeedView = false @State var isListScrolled = false @State var listTitle = "" @State var isEditMode: EditMode = .inactive @@ -184,7 +183,6 @@ struct AnimatingCellHeight: AnimatableModifier { isListScrolled: $isListScrolled, prefersListLayout: $prefersListLayout, isEditMode: $isEditMode, - showAddFeedView: $showAddFeedView, selection: $selection, viewModel: viewModel, showFeatureCards: showFeatureCards @@ -240,10 +238,10 @@ struct AnimatingCellHeight: AnimatableModifier { .sheet(item: $viewModel.itemForHighlightsView) { item in NotebookView(viewModel: NotebookViewModel(item: item), hasHighlightMutations: $hasHighlightMutations) } - .sheet(isPresented: $showAddFeedView) { + .sheet(isPresented: $viewModel.showAddFeedView) { NavigationView { LibraryAddFeedView(dismiss: { - showAddFeedView = false + viewModel.showAddFeedView = false }, toastOperationHandler: nil) } } @@ -346,7 +344,7 @@ struct AnimatingCellHeight: AnimatableModifier { if viewModel.currentFolder == "inbox" { showAddLinkView = true } else if viewModel.currentFolder == "following" { - showAddFeedView = true + viewModel.showAddFeedView = true } }, label: { @@ -405,7 +403,6 @@ struct AnimatingCellHeight: AnimatableModifier { @Binding var isListScrolled: Bool @Binding var prefersListLayout: Bool @Binding var isEditMode: EditMode - @Binding var showAddFeedView: Bool @Binding var selection: Set @ObservedObject var viewModel: HomeFeedViewModel From c6517ebb8e0070e612aa57e0497c7b5420e8a4d1 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 2 Jan 2024 16:18:01 +0800 Subject: [PATCH 2/5] Better empty state for the following tabs --- .../App/Views/Home/FollowingViewModal.swift | 70 ++++++++++++ .../App/Views/Home/HomeFeedViewIOS.swift | 88 +++++++++++---- .../App/Views/Home/HomeFeedViewModel.swift | 33 ++++++ .../Sources/App/Views/LibraryTabView.swift | 11 -- .../Sources/Utils/UserDefaultKeys.swift | 2 +- .../Sources/Views/Images/Images.swift | 4 + .../relaxed-sloth-dark.imageset/Contents.json | 23 ++++ .../relaxed-sloth-dark.png | Bin 0 -> 7059 bytes .../relaxed-sloth-dark.imageset/sloth 1.png | Bin 0 -> 14022 bytes .../relaxed-sloth-dark.imageset/sloth 2.png | Bin 0 -> 21166 bytes .../Contents.json | 26 +++++ .../relaxed-sloth-light.imageset/sloth 1.png | Bin 0 -> 7011 bytes .../relaxed-sloth-light.imageset/sloth 2.png | Bin 0 -> 13734 bytes .../relaxed-sloth-light.imageset/sloth 3.png | Bin 0 -> 21049 bytes packages/api/package.json | 6 +- packages/api/src/apollo.ts | 2 +- packages/api/src/sentry.ts | 30 ++--- packages/api/src/server.ts | 8 +- .../web/components/elements/SuggestionBox.tsx | 32 +++--- .../templates/homeFeed/EmptyLibrary.tsx | 35 ++++-- .../templates/homeFeed/HomeFeedContainer.tsx | 10 ++ .../queries/useGetLibraryItemsQuery.tsx | 10 ++ yarn.lock | 106 +++++++----------- 23 files changed, 354 insertions(+), 142 deletions(-) create mode 100644 apple/OmnivoreKit/Sources/App/Views/Home/FollowingViewModal.swift create mode 100644 apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-dark.imageset/Contents.json create mode 100644 apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-dark.imageset/relaxed-sloth-dark.png create mode 100644 apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-dark.imageset/sloth 1.png create mode 100644 apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-dark.imageset/sloth 2.png create mode 100644 apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-light.imageset/Contents.json create mode 100644 apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-light.imageset/sloth 1.png create mode 100644 apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-light.imageset/sloth 2.png create mode 100644 apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-light.imageset/sloth 3.png diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/FollowingViewModal.swift b/apple/OmnivoreKit/Sources/App/Views/Home/FollowingViewModal.swift new file mode 100644 index 000000000..b9c42c539 --- /dev/null +++ b/apple/OmnivoreKit/Sources/App/Views/Home/FollowingViewModal.swift @@ -0,0 +1,70 @@ +// swiftlint:disable line_length + +import Foundation +import Models +import Services +import SwiftUI +import Views + +public struct FollowingViewModal: View { + @Environment(\.dismiss) private var dismiss + + let message: String = """ + We've created a new place for all your newsletters and feeds called Following. You can control the destination of + new items by changing the destination for your subscriptions in the Subscriptions view of your settings. By default + your existing newsletters will go into your library and your existing feeds will go into Following. + + From the library you can swipe items left to right to move them into your library. In the reader view you can tap the + bookmark icon on the toolbar to move items into your library. + + If you don't need the following tab you can disable it from the filters view in your settings. + + - [Learn more about the following](https://docs.omnivore.app/using/following.html) + + - [Tell your friends about Omnivore](https://omnivore.app/about) + + """ + + var closeButton: some View { + Button(action: { + dismiss() + }, label: { + ZStack { + Circle() + .foregroundColor(Color.circleButtonBackground) + .frame(width: 30, height: 30) + + Image(systemName: "xmark") + .resizable(resizingMode: Image.ResizingMode.stretch) + .foregroundColor(Color.circleButtonForeground) + .aspectRatio(contentMode: .fit) + .font(Font.title.weight(.bold)) + .frame(width: 12, height: 12) + } + }) + } + + public var body: some View { + HStack { + Text("Your new Following tab") + .font(Font.system(size: 20, weight: .bold)) + Spacer() + closeButton + } + .padding(.top, 16) + .padding(.horizontal, 16) + + List { + Section { + let parsedMessage = try? AttributedString(markdown: message, + options: .init(interpretedSyntax: .inlineOnly)) + Text(parsedMessage ?? "") + .multilineTextAlignment(.leading) + .foregroundColor(Color.appGrayTextContrast) + .accentColor(.blue) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.top, 16) + } + } + } +} diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift index c21248456..27cd7e70c 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift @@ -79,30 +79,73 @@ struct FiltersHeader: View { struct EmptyState: View { @ObservedObject var viewModel: HomeFeedViewModel + @EnvironmentObject var dataService: DataService + + @State var showSendNewslettersAlert = false + + var followingEmptyState: some View { + VStack(alignment: .center, spacing: 20) { + if viewModel.stopUsingFollowingPrimer { + VStack(spacing: 10) { + Image.relaxedSlothLight + Text("You are all caught up.").foregroundColor(Color.extensionTextSubtle) + Button(action: { + Task { + await viewModel.loadItems(dataService: dataService, isRefresh: true) + } + }, label: { Text("Refresh").bold() }) + .foregroundColor(Color.blue) + } + } else { + Text("You don't have any Feed items.") + .font(Font.system(size: 18, weight: .bold)) + + Text("Add an RSS/Atom feed") + .foregroundColor(Color.blue) + .onTapGesture { + viewModel.showAddFeedView = true + } + + Text("Send your newsletters to following") + .foregroundColor(Color.blue) + .onTapGesture { + showSendNewslettersAlert = true + } + + Text("Hide the Following tab") + .foregroundColor(Color.blue) + .onTapGesture { + viewModel.showHideFollowingAlert = true + } + } + } + + .frame(minHeight: 400) + .frame(maxWidth: .infinity) + .padding() + .alert("Update newsletter destination", isPresented: $showSendNewslettersAlert, actions: { + Button(action: { + Task { + await viewModel.modifyingNewsletterDestinationToFollowing(dataService: dataService) + } + }, label: { Text("OK") }) + Button(LocalText.cancelGeneric, role: .cancel) { showSendNewslettersAlert = false } + }, message: { + // swiftlint:disable:next line_length + Text("Your email address destination folders will be modified to send to this tab.\n\nAll new newsletters will appear here. You can modify the destination for each individual email address and subscription in your settings.") + }) + } var body: some View { - if viewModel.currentFolder == "following" { + if viewModel.isModifyingNewsletterDestination { return AnyView( - VStack(alignment: .center, spacing: 20) { - Text("You don't have any Feed items.") - .font(Font.system(size: 18, weight: .bold)) - - Text("Add an RSS/Atom feed") - .foregroundColor(Color.blue) - .onTapGesture { - viewModel.showAddFeedView = true - } - - Text("Hide the Following tab") - .foregroundColor(Color.blue) - .onTapGesture { - viewModel.showHideFollowingAlert = true - } - } - .frame(minHeight: 400) - .frame(maxWidth: .infinity) - .padding() + VStack { + Text("Modifying newsletter destinations...") + ProgressView() + }.frame(maxWidth: .infinity, maxHeight: .infinity) ) + } else if viewModel.currentFolder == "following" { + return AnyView(followingEmptyState) } else { return AnyView(Group { Spacer() @@ -293,6 +336,11 @@ struct AnimatingCellHeight: AnimatableModifier { if viewModel.appliedFilter == nil { viewModel.setDefaultFilter() } + // Once the user has seen at least one following item we stop displaying the + // initial help view + if viewModel.currentFolder == "following", viewModel.fetcher.items.count > 0 { + viewModel.stopUsingFollowingPrimer = true + } } .environment(\.editMode, self.$isEditMode) .navigationBarTitleDisplayMode(.inline) diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewModel.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewModel.swift index 425b5465f..6cc43df1c 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewModel.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewModel.swift @@ -37,7 +37,10 @@ import Views @State var lastMoreFetched: Date? @State var lastFiltersFetched: Date? + @State var isModifyingNewsletterDestination = false + @AppStorage(UserDefaultKey.hideFeatureSection.rawValue) var hideFeatureSection = false + @AppStorage(UserDefaultKey.stopUsingFollowingPrimer.rawValue) var stopUsingFollowingPrimer = false @AppStorage("LibraryTabView::hideFollowingTab") var hideFollowingTab = false @Published var appliedFilter: InternalFilter? { @@ -325,4 +328,34 @@ import Views func findFilter(_: DataService, named: String) -> InternalFilter? { filters.first(where: { $0.name == named }) } + + func modifyingNewsletterDestinationToFollowing(dataService: DataService) async { + isModifyingNewsletterDestination = true + do { + var errorCount = 0 + let objectIDs = try await dataService.newsletterEmails() + let newsletters = await dataService.viewContext.perform { + let newsletters = objectIDs.compactMap { dataService.viewContext.object(with: $0) as? NewsletterEmail } + return newsletters + } + + for newsletter in newsletters { + if let emailId = newsletter.emailId, newsletter.folder != "following" { + do { + try await dataService.updateNewsletterEmail(emailID: emailId, folder: "following") + } catch { + print("error updating newsletter: ", error) + errorCount += 1 + } + } + } + if errorCount > 0 { + snackbar("There was an error modifying \(errorCount) of your emails") + } else { + snackbar("Email destination modified") + } + } catch { + snackbar("Error modifying emails") + } + } } diff --git a/apple/OmnivoreKit/Sources/App/Views/LibraryTabView.swift b/apple/OmnivoreKit/Sources/App/Views/LibraryTabView.swift index 1fcf44107..6fa328866 100644 --- a/apple/OmnivoreKit/Sources/App/Views/LibraryTabView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/LibraryTabView.swift @@ -21,9 +21,6 @@ struct LibraryTabView: View { @AppStorage("LibraryTabView::hideFollowingTab") var hideFollowingTab = false @AppStorage(UserDefaultKey.lastSelectedTabItem.rawValue) var selectedTab = "inbox" - @AppStorage(UserDefaultKey.followingPrimerDisplayed.rawValue) var followingPrimerDisplayed = false - - @State var showFollowingPrimer = false @State var showExpandedAudioPlayer = false private let syncManager = LibrarySyncManager() @@ -74,14 +71,6 @@ struct LibraryTabView: View { var body: some View { VStack(spacing: 0) { - if showFollowingPrimer { - PresentationLink(transition: UIDevice.isIPad ? .popover : .sheet(detents: [.medium]), isPresented: $showFollowingPrimer) { - FollowingViewModal() - } label: { - EmptyView() - } - } - TabView(selection: $selectedTab) { if !hideFollowingTab { NavigationView { diff --git a/apple/OmnivoreKit/Sources/Utils/UserDefaultKeys.swift b/apple/OmnivoreKit/Sources/Utils/UserDefaultKeys.swift index 8aa1cfd60..8e8953575 100644 --- a/apple/OmnivoreKit/Sources/Utils/UserDefaultKeys.swift +++ b/apple/OmnivoreKit/Sources/Utils/UserDefaultKeys.swift @@ -28,7 +28,7 @@ public enum UserDefaultKey: String { case recentSearchTerms case audioPlayerExpanded case themeName - case followingPrimerDisplayed + case stopUsingFollowingPrimer case notificationsEnabled case deviceTokenID case userWordsPerMinute diff --git a/apple/OmnivoreKit/Sources/Views/Images/Images.swift b/apple/OmnivoreKit/Sources/Views/Images/Images.swift index 8dd6c6fe4..f90d34ede 100644 --- a/apple/OmnivoreKit/Sources/Views/Images/Images.swift +++ b/apple/OmnivoreKit/Sources/Views/Images/Images.swift @@ -30,6 +30,10 @@ public extension Image { static var readerSettings: Image { Image("reader-settings", bundle: .module) } static var utilityMenu: Image { Image("utility-menu", bundle: .module) } + static var relaxedSlothLight: Image { + Color.isDarkMode ? Image("relaxed-sloth-dark", bundle: .module) : Image("relaxed-sloth-light", bundle: .module) + } + static var addLink: Image { Image("add-link", bundle: .module) } static var selectMultiple: Image { Image("select-multiple", bundle: .module) } static var magnifyingGlass: Image { Image("magnifying-glass", bundle: .module) } diff --git a/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-dark.imageset/Contents.json b/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-dark.imageset/Contents.json new file mode 100644 index 000000000..8df8ad011 --- /dev/null +++ b/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-dark.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "relaxed-sloth-dark.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "sloth 1.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "sloth 2.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-dark.imageset/relaxed-sloth-dark.png b/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-dark.imageset/relaxed-sloth-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..5a9e8c0ef31f5939dcd20be16504abd4528b5d5f GIT binary patch literal 7059 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�PO=dl ziibZ24~L0v{i6r_yy3@(O=)TAW?j6w8&c+s>VrWLYWJiqeeb^rUV5x_HtA!flYU+Fr+QSqeM+9OO~UvL1A zc-cb-<|CQD`ZXcId~c%eyT7)M=)-iUygf4c6cNr7IY zRqx<;N2ULrWK^L7jA5~}(}g)e2_t00x9Movr4(j)150k^Mld)SVTzpk>(Mb^#UJ4u zLoaEE`TA|fd>jaz+x$A=IS#CeE*dKo%VuxBkZ;xvbQeACh*vFl4&<})AJ_?^LT(UG zO--d@vd0P;r(;fKTv0pKhua@*UhK}R5+CSoXt2_EjJG2CJ2zDVdxIzjsgL(!98v~D zT3YbvLJ3$QiRJ4I3DvDZ64XcN?rfUV-I?Hnf=vA5-x|2WtLZ9_eS7AP$V8U@$DDyE zDmxab&E+A4#?1W{19_P;ExPfaK-fuicw}KmU{Ys3+XJf<;QB`R2xuRiqpecgLA$v& zWgzXHMwLWRfp22!8FI6vNZ;@YG!x4Q;!@G8VsU%u-5-|ZWyKp{suo|gpU#-?H3~re zbpCT0lws^GuK|iTphQl!wq{CT9{~qg8yOj~&G6A8S!%Hdr4_B62!N!9hq9fo&CN*B z0qR)$Mg#7J*4pXSy$uSb zSo#g7W~7vsque&@Wz7)=3)_o|W%D9k_LZ6XZjqn>TS}1ijCX;S`_ps5CRnos0enzl z7Wrr5W^k&DuXy63b*tI>JSQ63ijG}<+hIcEUYR%5x{^+nZjH(+#Z(=?a%}M4XgDT( zjwqQne1b-v)Arb^%K#5t7LCR1192&5m(ybRl6`b@;7BMo7o(I=2yAE%+$}dQrPw+M5`T=7mQ(@wTNqB zY3cdezX-ZV8jqM-$+2Fn@pgfRc$0F!4$V{oG$R{sQ#6YSp@U#V=Xm)Vr}mX`#euu> zlb(j=51ks-Z^yEQuK6Q{gZN3%#=~TuC-Br^hS)PWddeQ{KWQtmJ1Q5lajTRBbH^tO z*$Kqw3cPbWaF}319@-;DSg1}RM>J?)!fg^OYm8$Y1U87pWqGr!0XD^qKsDTDExG%q zzqNqd*^6QFpp%FU-OX7gaW>QFg0AZ}gpg)B=%a5d>NTN&KRgjyC#@>>O_@uT_6!5K zdW7l8C&3A(QQ}o0^2l8io5Bi9VJ8^h;30fjU#P?L{*1oa^C>P)!m`KS!WQ ze0>H-Qe;}MUTYP<_C^WiS6@rv50t(T{!&rBkiTK%ZB0m)8cy~l}J{^%n)O3=hXrnDvd@GfQIP6i3%HcIMO}-Gk9s_5` z!4@)>HnT#-B!X}iFY@B04H}9$mKgdzmu$`P{74Yj?aMwH)7w>QPv^be+n$|4N{|c( zf9DqYO4e7;yZ89x?E_Ns=cQp+pND?(x2b`FfzV{-^>Wuz#JPfJV_^Cet55kMP0Eu) zT(dobcGHyg)!uM`H()t8HS|LTi_(^#rvMsz6=W%xhL-)8VlSoF>+RzE>BigXhL0ik zz)k5Rjlb9BAUK z{O;ph2Tpu4&FGIopIzwMeij-$Ryii074u&IcjX!Gp04`c+go9#cNa}ONBMa2UgKfE z&G)I)_i3Z&dF{NL1vznWK@-)~Iw_^4;ZUZ8YT}nQ;(~a|4@;AZL`H z*p!EvOkeb}0-KxSX@VPT=jXNFp4N}RL)wCtNz5qz#c2fj?|s|+Lt9{*uNck#bub!& z?`@UeYK89mP+4D6$=@zQr;r|QqE7;Bd{cojn1jG~pFv@|gntOfYQE8uo6GZ(wYC+> z5jr<^Yi^ZpD+=-|--BHZPtyZCT+a`6QbYF*w6zWh+%i>RkNN=JZmfFtJa<1YrnW@Z z;hAloroj0<3->Mo+Q&OEi^0~goXys))?(d|`ufZ4-QC^X?x&;5jmNvzp4SYnV2lnj z0%fTU82njehh6J?tK!}6`&JREWD!M5nsV3E=X8jgd}qLRGxvE*!FEs`$_jpnrkwh$ zjX-nBwhD1TX`xzV3yp5>B1@ma*40(R{qv^gtY!r&6AKIfF~eG;TWu=$Uk1JEfRdgV zR2~817_+3lOk=03%$66Ofm)iyV2sxCGodT>s0B4D;k)`+1xg3RztvXp{36x~X?Yq{ zy60|BI>HOb$F>`bidm9&KYnPibY90mkQ$6pwq471-&{MJ61mIqQb8!x^sse#cq~1%EF6M@lqNfS$9(n1 zS_Y0|$%5={oMTb@lDlS);Sr_p*HEUW(W5 zR8#dJGZ0yUazbao*;id%TNmvQVIK+!11zUvm}Q26nFQn;K=J;=n<)+Aid?$XeWmyl z$IIwQy-3K}hL*K$Q$)E91j|?@eIqs^ggd0s(bU!ieC2 zRGdvy(?9dvnI>#Wyd(l1l2JNRQqsiuX_fH6mWSmajKOA1!LW@K-;GBd^a$ey5lr3c z5!o>l-mGKSO4Y|Z3{@tOCWM4nevI@WgYk>0po_pzC>%b7-w>MV@#+L&6qGUx-@hDw z$Rj9`wx*1AZPV0=`4RW{1f^Hb^YG-%G!!kyR7nw&tq<}r6WCZ5W+UY^+!#diU!;tfFeT0dc?2G*< zJkUSSOp8gUdSt=fOz9U~mjurHgqFFGh~YOtuxm6a4o*3s(S^Ct*+Q#CDchryriir( z5IIq|*P&b7Hq$fXF9|E&r@b(`b9!xvjDZ9(Z z6zt1N&x&>}$+)9>(SVJpmy+j-isYQ*83BND_@$gi{e&A*{LisrT9cE`65;iGS={>CcXAJm1?V) zd?C}AOkl04y1M+BqtS(hA>kz1-KT|xz4uT>ozdklwRlfM|NcEBd7Skf9H0Y;^ephz zUZPw@Z_lk&#=AW6;ZJJ9f!G#FeyT2e&HC$@@NS&n@ zj=&gU#f-({6knJi{1&0-zmpLr>cMaUU>O^U$nTR6CD?T?&9({*CQ`^cyS>rx9wsoB zV6gOx8}IiudiE|9_Q8U3ys=8zla@KkC%iWWM&R$V`wue4(PZOz%V_P;e4+@x6TTG{@>&+kDj@%LS|!>@IkWou!025-~fUzEOb zDQy`PCfE6Tx1!{Aow@OX!Hi+4^07TeQMhDK@m;s_z{PAb=PPTqfVz8aoo{;+wK4#d zuOe2somjxsH}fW2{CC6ANW@yNaS-1_Fd$n%;5Z(8rt;Qf$LhMp2RG0MST;)3wqRlN zGuV=m(b{h3t~k};38S{_Zdnq91c{=C{SB~v)zOv9czr&9xDWjJv4<9&z24--SDn{) z&)2fZYzfL#;gLb!wG>F|A+kS+8D~f%fDUO=8cZ+&I^{_(cytOtQlj>0j_ey3=lioY zVGZzuTHBX;8CsHCPx&2h*W}7`vqPm)suDxzpEcisubE1|PniO4=Z>-fTsLxIA1_2W zIY5E@*mpT+;XU*SAdtR50!IN5kOVOu^?jOre|&$Pc^%%H>l6NrUf^8w|!_RN@2^Is$vP{)TNP}^ZC?|5~ru2^cbjoHm}-Y|Qu@W>;^N#6AsP|JFi;pE^Y7m)x9Oro(#XehD2i3vXkt`SLR7xd zCt6$~MxHU7n46a{jB72;Ei7ni2(MQPRZm;Y+3S|8UwoMFcvxOt)l&#_NgCS~-^RR^ z+8L(CDkRJR&Bo1OK@g)|3+a>h=0j^4Qu@pnT}b8<>fw@{8d+esY-PP)D_VADiT8kz?8$ z_;fqe_V#hO;d`ZeX(kuUC-FeKt-u3P70MedFXSyXLp#GXoy`CweL%_Fr11884&kcR zv^qFk|GJYkK{!N)pDGUBx3}x~7wM5KfK=;dVEjE`_A_3kjy)1YR5R;4FIu}T&DD}Sl=S+ z<`c=c5LqwsgvIO#GRLfhE)*qR-%KDNv4+5Nn#oR90bvmxr(*SW zh!?Ic@4{9!jG}?&5QQ67!a*~9TaBUSL94-x$oBhh4Tg`116ZTGS4pVUaBFm_L_?VCym*QU>p*j$9SyMPt_f>6WKc!*PW(_$Jo6YSD%g-eU{4=~5M4852 z4~}3_s)ED_*sed7tZ4GF5%Eg=4Bo9nRq#athRDLHkX`B&PO~j$gi9DNxaCgB@>Oi} z6(@WrY`=VD?C|Y|dO_C}%9t^J#@jy~fbZ*~?<fq048I4@^5 zZA0Eh_B*0$uak2xoyCY+&`~i<4V7Lxzv_t0O*xA#iO}t=ki%Y7X2>=a9 zPjd3Z)bqysTU$tf^{?f+^*(0qe`kW;?L6PU0a2V1*r?-m`unta7KT)jU$>(m?Zft7 zPqVpiqX!4S&y&Z@Ce8F%QYX;Sq6N*Y${OgingJ>zO05=Ke2;f4cJRM>Ts}4{Y74hf zvW{?OFpJw7Hh*nwSilrJAV!@Js@_I+k@vo9d^fi>HGQZ&a-*0q)YsR~{;RdY*VWzf zRLHvF+tVh6h+wY>(A^GX%44M%8)KB-__~BdeS|KD4LMn zuOY9xIpC;!-^Sa!i(v#N(q2qED3Y99XyS3$&vqkI z$J@eh|7t0YyghnU!F3dkQ-f5%2`&qc^EZN}2(s(CZJ7-yt1+u=1Yxlzts0kEy6Ibi z>6arDl;zriF6t$vrSIN7wA=SJ)wTVLXF(MFzz}9Jtzjz|9NDqe;xe=`-9ms$WgmYQeU z!Q$e9J^24d7-A0E6o6s(&_SHfXFhHOC1Ur<7H>08^ndPOhyBXOMV0Ibagl)!-EvDU z-Zj(K*G{&UlT-a<|5oQfKu8*YSta-8$2}2Lt^8 zZe7~-&xOu%UA++;Fh^!~iJY|4egqZK7Z0@5RQ9PUbv{XBrLp7!u9Nh3bPf7i9gYK7 zVp=}WcWVh@Fn5I-7R_u1-6yu3C^i(Xrx{mpQ#X%+OXvy;BP=chU)^d@z-=}gQ}coy zGMQYF=lYd_kth-t;^Fb7rqM&CbMHzrTv8W3j%_!_;l0btM4fW;(W-|{Pgi910LC3$ zm0(QDhwj4)`O42|KpVuK>)yB5tID1yQ6*(PSeB_3yPk2+)7A}F-J^ZhaHoARKt+FN zVV-DjRq`m_DBVBw%3X`G%B*L>eoU^2p47imy?{N;J%72EG!AK#+oo)ihDV2I2%{QD zd=85N=*1C**_ZLf-pJRSatWP@?3;v&9fi<^|2<>sRnAh)6y(4ubdi&bi^|v^vt2!u zk55a8F69G$`M)fwzS|HU-SlyEuJI*Oi=@w8Jz4~^t?TXghBAN)B8t%?+^=3QY3cDg zD)owh)|M8<5c*tb%xw`dk>p)ai0>MvkQBT|)$)U4*}wRylKcg?O{1-&zoDgtC6z@V z8^5kv+wD!iNFhqGyA{A3^7|ynrQ|I$dMbKoEQOem@HuV(?rcV?P^eiYVHS*~8J;iP z@SW%2`drzzt3MRo%y#_dBRDXabVQH`26buyO+w)L?o{pk^4C;mIF#Zke<*bMNzbcN z4$v|qtcX>$U0%EGoBH>hp(Xp*@bjYgvAxL;>XYY_@U31E>bqMM(e<0PVxDH3Mk&d& z_T!pDQN*jh3jgM2Y33sqXkE0`bAiCX7f(dlejSsz$@}9pN`q2qX}|8G%#gN$0bXXk zZIs&Qcg=jI`BgYnPk*HRue##0!{Y7qug6@3twIt|A~$siq`QvDs43xVpihxVD8}*i zN2xU{Qr%F&Q2#cJHD=G^{53-A^^LQ;sKnopab)gMj;N$4qX5Jh(o9@bTGq6_Tq6}E z9p0YyDEgwz8M$eeRJrh<919t>h3(zlR+1dixZs0(VzefKw454`ORCiH_Bv_!Gt|~1SzvN4Gv3N4|tFr4AWmF5Iv7Cvw?KZ|PZP9FpZZ+`By-k8_u0s~L%pg3n z7|U_;iH}ENe8y9MRG5xxQ1fZfM4jieS5dQg2Qd2~8S%;{)-TG;ESdv=OdN&?6Wjnw z>S>w7p%|Dt^e*ktUyb~XDUm6}+=kSgCdB8fF-0yn-kmp=>WO}D5JiDq**&Mzsu4;3V%^`iF!JR+77gON z0k;)ndf6|7<6HvMG9T!YZO?EKfy)*&4J3~>a33sN=nr+~#MIc5$V@n$-B z*H}d*M30O{ktU&wxBH)XN_rI7v$KzQVrZi*eGs|&kIm!yR{aE}1xaeol!uC3JZfig zoG?JElrKp!_r#4{f`T>@06V(ouys;ep7bzagLI%`g*0L+CDRFiH@-CHmh7D@FNsnT zGRlOuR;>SzGgaRxHS=Bu^~$NLPbnV8`o%;@l%vcZe@MByjb|5(KlfAB$ZIMHdvake zz2d_&o%L)tOQP<-_1}}KQ>K0U=E$ndf!+N!H53jaeBFlC4HgRiL-zwdg^(vKdOg76 z)0zP8g0W_O|D14;+nURwjq<&PN>!h$au#_L8sT=JOj5dIUS<@1pDmfDrsh}FX*_72 zg8@QtCoBqXK}j}SkLxo}YJp|fvBZ)Xz?_XKJz6h6HXA8AW7A*{@>FjNhCS!MJNwHh z36JMcn^RJU089(x#&hVOLg9fm?s)3ucP>tEr9aYjy$$&Ti_0iC!%-D6c!Qd2Av#BD zwXmq^n^cm#pz7vsh!?I<9+9u(b%tt%D+VVe6;k~BAg3hkBe)&Tipc>LOTuoNvMtW@ z1JH&PLIQ`B&%CfTIx2ev;*vb(nav)WyWDYAP-27Ukd-T5#|ir?s;51zpILEC{d4a+ z_wi3tQBaM*p8`e&EARpBcox!=7a)~d!8wF(H6L=@K!=(@g_ATAPKuqv_^n3En3Un0 z+Y^Wj9@=wcbMpg;t0u_;PM=pfungY8V)%g(nrohK$ji&WFtSJGRBgEwgC4U=S_&$J zIp#uHPZV=MWzvnq+tj1a+wy6QO)15dpkJb-PC1Xb`XJ;l+)YMe}Tv*=R?4=D2 z4fRn{&7<$jaY;Lph*Te#vK#nHysbO8%|jCe2Ty)QSN&vDhdxVkvBFerVVaO<#C-ce zSiI}FhCEjHX{PWW?%s3sS#l&dE~;7ovCOQ9qgsV{i5iyp07}20uk&2?TcHfd=e9Y+ zP0ygtb*UN02+`y0miJ$B?z`AT&*Pq}tG2R~lr%LH&mj72p0=zCgYA(6tt_%>l5LxV z;+Qu$gl98Z`yqN@mZ?u^Oo5+xZzM3#RU!CXN)5>{vACG}oX_`7!45b~4C?!^)!(M4 zXM;Crf(PtI{~V^$Xw}$)K7X#b>vVvo%Ir=ri4UISsY+cvaEgG-X!!VukoiVbAw*c- zCL5ib%;plDK^M6UjXH8%5ZD7;jF)9Q+z%62y?9v)w0^U8KG#6x)zYl48dD9{Tip9~ zERD5vbTs#`_8HC`cg}kkF$eMhQlG?;fCl24Nn^?CM*wyi4H;?h@XOJ5RP(9Wl|G&s z-bZlGl+Q*Tw@HrY>FV){p?I8;u^z_#+g9 z8TmjE=h`KQ>^?Q+=;o7*_-bC1%gDC>Vn#c*1of(#we=Y1(OBsKn^Y^3&-R}v0tA+3 zMI&JF@l|oE;T_X3pSw7iwewgzuq#NpvAvy!C7`EzP3&WxAMgrul&Z>BYeCrausBC- z=_wbh>`G%G#HL8W*C9-b_LH>EC5NA~>!eMPrk&;66k7I+l?n*XHSNY$Ktu~;0T`aWVL5;$XV5>W9Q`a-@Dh;HN_ylQe+lFs+V&(6ScC zQz$S)cMc8pQcDLYh6a?qd(}?K>b_5swKceNUsUlkEu070dm4( z;N!D);U7FIZ0Q~lbwtDR;D(};Mybn?BWl%IM&>`&(fa%{GBz~SE%xMs^O3SVpd!MZ zeM({+;Uub3u}}4=o@7F(#fa|TGK*^0MvfTKc(w&$X<>z8kfVHEVJYA64s9?(C+APf z%*iMCoSfp>Kx$f5fMLBXhSUeKPyGA{ml55}-7YPTQ!QOCH^NyB;7d5|PEM$t`#pNf zyQ}yL>o4%bqdlX7;^=2Uo&5EXu~~YtCAG1df4zo%w0U#6NEDdU>|SLi1xTY>2A{#a z*oWgWeq}DkzdT)f5=L+Y`_jNAM2*1SuuUg?9%U+_6QC9JGe9S6#v&s|bb>%GIhlJ| zc3Ha^6p@cl`%famLgF`_hVh>I^LLtX*W_hI9qr zj&L`LfBjBZrv2hX&JTx$%7m~(V@53oS8uOWS!gl43w)_tO;|SC{QArDVyc2JX~UQDyh6~ zHk+Z(OrOIxbG~+P>Ncrt*VnfJqdj&)Xf~Fyu*rb+E7I(gncfJ);Qlo6F%`8tY4kup zj-lv0_=lM}ZV&(w?|LsO-0U20yP>%7znEljpX9wv~F5P(Uoevr9pLq(w4(Vo8gi zlY3q#D9`2}&TJG;0dni>CHXV*Lg8F4YP!{98Zt%Dl6;4%Q`rKaSr>U_4*#vY0yd2U zdr;)uoqhyO}vo|=P|~BEw{9vs$uNQV~m|t z#kcc`qu9C0B%GVHGfP=8;U4`Z78(@^Y~emL^OQYfck-&lkRrW8OC8ecUNJpL16`4@ zzv*ECSzFJUB)6#C?1xN0&u{`;W*1X{`##v`$n~ z-G7VJ57DPp;Vo|fV4xhLF!iCyv2bXGGPNEkWZ2H+=lhGVy`9QIiH`*8PgKlCq|4CF zcDuL;V(?N89~&Y<|Hk~#CySewJ;}>73j;_^&`?=!Ylq@tP+sts&$E(W6BW}+2@N#} z^p%)3TQ>o!cS0r$Q%5It#1cN(Cog9>)I>*k^r3Y`hXE5UkdQ-l+^2%gS9m3XRN5vU zA|854ABfwcjcMsZ=)o(B*7j4;+UAmZdNnpmHF=oW#B_|!^(vV8tOq3;N?PVspZYu7 z&)IZFX!HnAv?)eEiGgui+T}6}?-PEoS~8gvNMp7-X87%l%Ql&o!dJ%WTbyiP=RU7~ zhW?Sb-)g*}8V9G0)`p0P6K#8rXzxqCiH-9>#9Q7DJz5R*F9I^M$D7`%%@4oQ|kFl;@0Yoc&;1n}4n8H)XuxLb}J8ct8W`b$b^ac(>b!r33$n;0`-6 zKiaU*pWAFpz{Qzd=eKrh0<@e?0-N_|f4k(aelMixp1E}5YZ+~ZfQM-WjIIpbY!u2s zC?<@KS$&=-7uP2Y!DcPi4AWJcy_@%Y+?p10Zn-`O1$!#gK}`s!1&Zt^$RRMg>T!mN zaO_W@sKzlJ{qcJWos&8!=OQ~UHgNvyeC&E+BG@Owotz>-9MA26q6i=2dYu+-%VdtU z9lllZj})#Lisr|vYX9U$wO-+a_s^lbUxQjAQch%U4%rC0AOzR|3zHB_lB#CFHx!Bx z7_nxzb2375-o&-=T+hg-M;7_|n8<2kx@<4DER#w>RyK12fZlAsl~Z7U6y_GRIkOnz8+; z&&i5wth{nm2C74XMVv|m{KVebAt*4|X@3HwG;jlBz*UUqNCxz)dkc{cF|%=QvX4BM z{eu>SY=6qZBXb2<$U4C$Bi^SH#m4RbFOhDJ^?ljl6~rrj@Nu}TI8kA5F33NIabc!_ zQ!%uUPN_jnmerQ+M#AgL{4VAsQ=?+=nwcu6}C6aU=19X{O$&b zmJGWMBKTWSnjuL_O3DBNMUZ@g1GLuRF8jqHHA5z^yx9kf)fO_4?pefYU%C=!F9~!e zuF@cpCyTb}REvh5LPBQOvv{RE8*Hw#mqa=o4%shZR?rZ zCu7e<9xSbwZ0!7nv}{5-^s$X@m?o6g(D;3s~~i2iR;^FRuDv zaV%w|S@a+j+I|E;You#EplU$B7-k`# z@uOb2c0(PCiZr+KMT^_dV6iko+`t;u;^sTu5Rp?9t8B7Z&tJdzy>?zQ#Ud2&H1p4R zWv`HTf=2?|#hvsmiNf7X*r`K=&u-kY*@dBXDPo&4Xm?n&RFA=CxaMqHL57Jz?A)uZ z3#a4>NUFKM*MfS6aeJw8@q)Re8Ntw+M39;HG<^^zYwd)DzC21wf(pVi=Mk2GQX;>fxdvkZyJl`?+j>{ymX%AD_YabS#-Ogw> zh|d@=+g!%Mq8UIRV(wSTMK4=C^o89IG*(wiK(mI3x$tq-l1jK2UJ*!DV*F=HaLF_& z5ocgvC%89_fZ^V35U~YF75K9fnqW3TQ5zSeS!KXD_J+ptLp?!X8G%Pnp5DZO#xe@rWDl)$Tkc)mLINK}~85wEtffs%n9k15lHfU;rzYls$ zC{bTcP3%fedaTaI3&g~QJV&%JfH}1Bm?yN()zDsd@pe+2y1QL`A7qMXg*5r|tJx`& zYfe^H9Q3pkR)Qh_ASwuDz)Ae`&!O=&;KMHrA2xg{+qAvG|LR9h+mZ;IUhgmXJ$3CN z_7)a0&|HdwYQx4w+j=yLkcfKXkvm=Rqv|Cx-7H^RCD(XHE_ALDY^5J#o!KhD7J*29 z(>(bR1_R8>si9exj$cAPM%5qCy8_4@s|n-(13{UTPMIwp$w&BV38y?_%m&E~%^DTm zwSqj=^56O5h+W3rRPWB$V(gi7OqUb2ZT|?*OXX0?;4jPbCda|U2#i?u5-CPhhb@tBL~03;$8x+8z&l2@Y#=O6i(NAt|tU?RZ=$OK1*{yZ4T%EZh(wmmP|=JnXX$^Od~+J|0?hkKRjU89HWZ1 zYdhFxFa;KCK>1W9C;5|%24IWf^i6 zWj_BGP>D+ABDV-PJQ6)z`1tr3nh@5&*(qrIGRh(?W-IuF!v@FQxWsc9SY*-l6U>pB zDXLQ9Y!nLb*h`6R2Xt^DVHVhq&|!``wrz)hUg|!@+Sj?)&sbvH^m~{;)(yt)v^`mC z3>A}kT40`)w92t4b}SYVCrhBfG1J!76)41e44sE3sOUm<#bwbA6ZP}knquz|q^>PO zOGvlvdF25P()@;jp_xph-45&i0t%P+`e>g_881cY7r7h)_5$*yj_F1o)~XFQ8U0)N)0fMv(6D^&L&CS$Oyw7 zs_YZ)_f1evl#0|y<*Q}!3Z%r9fRjsZ;4Z@{fim4TbPoB+kcyJuM%9Y8HA*Z9n(D)~XfrFYTWPprx5dhL}tZ&Rn1bJ6G%}i)!4X zMjp$+FcpGxDt7M~M^SdQA1WIsXgpvb9VxxYDS;zBa_i{ms2m!{xcZV*s@o{53l9SS z6h-G9i+vd`*5Rq!^^5#u$`V4?7-mh1Q2v?nF=)+9hBkm^0!Alf?|_%Si1V;R#vga$ z3bFv4TKgvB0Ntl)3)hSiFF7i&>Qp6ty*v&=&;o{lv_g#-Gwd?>kXEYVZG-Bi(gaOn z=&0?r+hqK?zlmWl0DDKihgf$1E#3}B|Imq6logv8i^9k&qe}tS8 z^(eC>i*v}818kt)(h2qZD!&#I-3n6fTWEA}N*25rk{mf;O&%?! zHnF+IN)mp%jC~hd)1(GY4Sbmt_rFF8j)Q~O+**F}C_5)qW4CArC4S6-B+t(y{e3B3 z{@eKdzlLi>^YfBVUqG06yB+Y*27_Z5NQVEb=FI=0{N6vFtpP38zW>Gd$Mblcb3d+g z-S>6wbKmFnd<~i*tr0q`EDyY+^VLnrm}#~B!9hmV>466CMugI8?FCG( zon<>7vSuQPG*`=HR+(E*cpN8OH|aaJ(_8b=T5s$!RG|^CeF}#VD0Ktg+)kxAwjW%) zpQ|1jyK9PQlx~O}KgacifJS@UZ;dNk59Uz;80#(h=nn$0SO95uzt;5rb!F z*9A~!w&x2&3LlBaVP9}PPT`thtLVv)3mxp*VJOc8EJCy@H%YXcAr+6oR_*TrI^3z-B_lP5%8de1@oWf93ybW~JLn!YkbVh0jlCxJ7Ty8-+di$wHX4SUEEb zz(CK$XE;ezM@It~#ndqWn3(?ct<2S~Nyk5j40qdlSvPYdxW|y9R~C$s=#V5y_Poqo zz)~Lv-EOwBZ-^HA$nH&WGqVAASPw5TW52}=I|4HR8^ncpI|9N>Yd zqe5MB%QxGHL`uI#R43Asg6jY<6$7wa?i+892USApXi9DJ%mpOT07134d&8GCmF(wb zqdIXV8~A!-%<#NXVx?$Gt@8Vgyw_xuiZ{OoN3A!1v8^bw4vbl!SZvXTW3zbO-!}5L zi}HkJQn{VWdUt{_qd|;|6Y0||oRawGkZ_HYifx_w10LAlhYU7jfly6R&F5n)R3-IQ zdj*gKaUZJ$FCbsv-IyQH+o-A(;b^P`J38>{+2vf;q!6R?6QXdpvRtw`*#$YCs&b~>t+S~fq=DZXbG(gVKFf`0o#Q;rthVB_fy2o0o-NB zi+m~4;?lz4>lV8B2_Ie4%hsTKRyd97#qWW-aewv;E8<`Meuo);-UGdnnr_t?oyRYL zhK|9iK2mOGV}@quZ(T!d`rWnslz8chfKg48?X}jQpKpBMm@}-7NH$0NZq1H|jgMqY z8QijXQ#B{cpK-nr-(kR-;T(<8N&_LM%lwOgaqCUngNA?it5{CgIhO8s0)uCo?1ZHz zPLk0^>SggY2@DFnePC%o-ET|MQV_#7KSkNRR-w~*CM#3svkDcsOw)!K63w3_A;gLY z)r%1Pv#!-epzb^ThF%O5(6i558_q6AeNRg&%&;Q)@0Y}8)(#a&j?-?|a_1PCzAY2x8?#c)d)mKhDX+UX2RDSH7 zB~Xf%X^H0xH}$f-17O={yCD7}d_P!hJvlMvp`320DflA=GNfXe)g6Wkz%S}}M(-qO zXN{8?5en3pvmvc8q)+~ZE?8;A`?J62TU~#s?a|S;64<1E88-4T=S(1*6QP}d)bG#7 z5XA%VjstytedkB%Uwf;pPEPUXhts|=V~K%p1bA{6Q#Hj_WCf94k00!%L>zy~C@b>l zQ$5h=a`nUh&u?)tOYe}plk0FR5X_G38Wx?O_B8p(bGp1G$R;7W{d$|e#A#f2SR7{{ zl2P_j%h2$p5?{O*f?F^p{%iH!8GRE@2gHa1T&}z#nE`{8QmK%@#g}k62oFuc*Q{lO0X5N`()koGGNyQon z_pd=&lFkCKcE*>Fb|u*3{}%ax#f0JSP&l&|%ev4WThYtnDzn%u^PWS)wJtPSvQ92R zYhsW}}Yl->_e+j|Xk+>`KnvuxFJ_IqlZfsp&>;-UdViywR=xij_Q= zBO?+HaGW9W1#7wW1PK!CpZs9#T!T0qD|E4g*GS5qe?VhJ_Hq97nh`G`>;E{@&Gla= zQrJxH=)3h6&Ea3)l*!S-6-`GP{qnRawTEj+{0WmuuQeS@BQ=*(jyabCvNo72@B8>w zc*UyqQ>08k`iPA?1)n0Lb$GJH*p*<*WJ25%y#hd;&{3}~A}l0_rQ8;~G+W*vmXaLI z{en??>Y?{!)cd5#6C~z@bJ@&1%^xy?Qc}~epjVQ4lhu;=)~9s|mw5H!y9hF$kR52f z`iIwsPt`?9AP-)V;7+osjgbW@kY|_(iSEbd`u7YFKX&$rXAdB6iHhp!BOC5Xk;c4Q z+ZKeN)}feVuTD{xMWdP@)SpiOpwPcp!^zJmm|w|(nWrDC){@vM*VbOsi5eBDczko&<9cmooH&6yY=WU>|3WCap^u>iTyuCxw7m=63Jzr@#EhNsry8u~U}CBML}oUU}W7 zc-*viG{0F!^b%*kzNwMGCsptO`sp_@Cg;IGL;usb0OEez^S@6rT8W?DBu!2_kH{L7 zoo6ZOlElhldV`OY=0~C1<;#+e zr2+k^ozEIvQrWg?V%}OlSG$5-6XQShZ>dm$O{wFuCUXW zl!|{`V#Zp(pA}Z~^hCxu5bxIIdB<%Yk{{C=6ZDmfz>3IY_GFzgOS_5%zucnNe(m>p z77)_77DBT{xPq`v0rhyWN;yHUrf7Cr*-TkYVJdorn=zj1c(p&sFAq}2!Qm6cT8u+l z8x91XP>qY6EG4E4@Z-R=dnl>B1#$oJCM{|D&~}T$Vi##dkgXzAa@8i4^MzlMuMp`J z8}*~~;kU;Nq+*D=tEQ&{RhZKN)3zO1b^UR8CS2m6olH#T2sfcXj!K*k@f$Wt~a9~N6Q`phs1d6M>pLFKV4d4k+kSF_acd3@+;rt;yb8^2xqCWK$ue?wN8hIkQ z1ZcaJMx0es2Ek3SL2W652A$ng5k_jt2%ue0x)0MbR#R4hboKZ5i@LfN+&E!hC4lUN z^e-YZw-j?MCj`4PY9mX4yz#mL=-1Pq?c%MfWxOF5SVrPX$jo~nHh}X?^Im!g{MLAq zX7<~Fjpyg5nFKG3=&eH~fA={%)oEq-9T;P>$fF*~CI(DI*4f>$1#mqc zaDhvOI1u+IN$K{y-?+Lm$bJzKPhBv%=}Ouw31MYfUTu*c?)MN`PPhI`xvXE`++4Ac zl4hqE0>r6Hu6eg_tcFhJ@|>QS(2?c#%svvXCr8$y!CvLFse?lT$_L@bUf@r*MbHXq z$K1)8H`n!L$xi8C4pI&nn4YM00?05WnSqDFe%U$$niBV0M(Hg|WG60OdNJp2fL%> z3=j|u2EPFE)VKBQ(~e!68-BB<`?$5RY&Vky@&OLaW}TKwqAahnf&b@*M2ga6<+0{h~NMX7LRQ>A?NIk=_h zG&&lh$3C5W7!T%O##)Izs#jVy&u_Zl(eFA~UnS7YHP^T-offL}G;yzXJFsCpsUPT= z9Dg$J+#ma^F1f`4>p@X2qc3-gzf>mu!X66jFAM1sZ&^zqnO~xKSy-4g@K+dgijTlI s$yG%ziF<-@UBHCx|F_#AX6rAHPL*(2AL`&+z+UnI&eYbV2J1okA2>bDod5s; literal 0 HcmV?d00001 diff --git a/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-light.imageset/Contents.json b/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-light.imageset/Contents.json new file mode 100644 index 000000000..0cd111630 --- /dev/null +++ b/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-light.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "sloth 1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "sloth 2.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "sloth 3.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-light.imageset/sloth 1.png b/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-light.imageset/sloth 1.png new file mode 100644 index 0000000000000000000000000000000000000000..02f0b0bbfcd2527d885be1e096bbcf4193f2bc3a GIT binary patch literal 7011 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 literal 0 HcmV?d00001 diff --git a/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-light.imageset/sloth 2.png b/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-light.imageset/sloth 2.png new file mode 100644 index 0000000000000000000000000000000000000000..f838edbc29c1809976e8627e1a1b0b2f03bb1b77 GIT binary patch literal 13734 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 a$xV|HTdzu-RzN?if>DrFm8q683;aKTz%rHq literal 0 HcmV?d00001 diff --git a/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-light.imageset/sloth 3.png b/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/relaxed-sloth-light.imageset/sloth 3.png new file mode 100644 index 0000000000000000000000000000000000000000..efa1a80e9213f0926f226c23bc30615848fa4bcb GIT binary patch literal 21049 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 F{sV%q`q2OY literal 0 HcmV?d00001 diff --git a/packages/api/package.json b/packages/api/package.json index 34d9b24fb..f1ff40840 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -39,8 +39,8 @@ "@opentelemetry/tracing": "^0.24.0", "@sendgrid/mail": "^7.6.0", "@sentry/integrations": "^7.10.0", - "@sentry/node": "^5.26.0", - "@sentry/tracing": "^7.9.0", + "@sentry/node": "^6.10.0", + "@sentry/tracing": "^7.10.0", "addressparser": "^1.0.1", "analytics-node": "^6.0.0", "apollo-datasource": "^3.3.1", @@ -151,4 +151,4 @@ "volta": { "extends": "../../package.json" } -} +} \ No newline at end of file diff --git a/packages/api/src/apollo.ts b/packages/api/src/apollo.ts index 7d4c8ea02..d7c29c441 100644 --- a/packages/api/src/apollo.ts +++ b/packages/api/src/apollo.ts @@ -102,7 +102,7 @@ export function makeApolloServer(): ApolloServer { context: contextFunc, formatError: (err) => { logger.info('server error', err) - Sentry.captureException(err) + // Sentry.captureException(err) // hide error messages from frontend on prod return new Error('Unexpected server error') }, diff --git a/packages/api/src/sentry.ts b/packages/api/src/sentry.ts index ac9bbc10d..d31f0b6ad 100644 --- a/packages/api/src/sentry.ts +++ b/packages/api/src/sentry.ts @@ -2,18 +2,18 @@ import { env } from './env' import * as Sentry from '@sentry/node' import { CaptureConsole } from '@sentry/integrations' -export const sentryConfig = { - dsn: env.sentry.dsn, - environment: env.server.apiEnv, - // Don't bother collecting and sending events locally (reduces overhead). - enabled: !env.dev.isLocal, - serverName: process.env.GAE_INSTANCE || '', - integrations: [ - new Sentry.Integrations.OnUncaughtException(), - new CaptureConsole({ levels: ['error'] }), - ], - debug: (env.dev.isLocal && process.env.DEBUG === 'true') || false, - // We recommend adjusting this value in production, or using tracesSampler - // for finer control - tracesSampleRate: 0, -} +// export const sentryConfig = { +// dsn: env.sentry.dsn, +// environment: env.server.apiEnv, +// // Don't bother collecting and sending events locally (reduces overhead). +// enabled: !env.dev.isLocal, +// serverName: process.env.GAE_INSTANCE || '', +// integrations: [ +// new Sentry.Integrations.OnUncaughtException(), +// new CaptureConsole({ levels: ['error'] }), +// ], +// debug: (env.dev.isLocal && process.env.DEBUG === 'true') || false, +// // We recommend adjusting this value in production, or using tracesSampler +// // for finer control +// tracesSampleRate: 0, +// } diff --git a/packages/api/src/server.ts b/packages/api/src/server.ts index 1bb75a085..584cd03bd 100755 --- a/packages/api/src/server.ts +++ b/packages/api/src/server.ts @@ -36,7 +36,7 @@ import { userServiceRouter } from './routers/svc/user' import { webhooksServiceRouter } from './routers/svc/webhooks' import { textToSpeechRouter } from './routers/text_to_speech' import { userRouter } from './routers/user_router' -import { sentryConfig } from './sentry' +// import { sentryConfig } from './sentry' import { getClaimsByToken, getTokenByRequest, @@ -56,9 +56,9 @@ export const createApp = (): { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - Sentry.init(sentryConfig) - app.use(Sentry.Handlers.requestHandler()) - app.use(Sentry.Handlers.tracingHandler()) + // Sentry.init(sentryConfig) + // app.use(Sentry.Handlers.requestHandler()) + // app.use(Sentry.Handlers.tracingHandler()) app.use(cookieParser()) app.use(json({ limit: '100mb' })) diff --git a/packages/web/components/elements/SuggestionBox.tsx b/packages/web/components/elements/SuggestionBox.tsx index 5118708af..2ed2af4bf 100644 --- a/packages/web/components/elements/SuggestionBox.tsx +++ b/packages/web/components/elements/SuggestionBox.tsx @@ -14,6 +14,7 @@ export type SuggestionAction = { type SuggestionBoxProps = { helpMessage: string suggestions: SuggestionAction[] + isError: boolean size?: 'large' | 'small' background?: string @@ -25,6 +26,7 @@ type SuggestionBoxProps = { type InternalOrExternalLinkProps = { link: string children: ReactNode + showArrow: boolean } const InternalOrExternalLink = (props: InternalOrExternalLinkProps) => { @@ -40,14 +42,16 @@ const InternalOrExternalLink = (props: InternalOrExternalLinkProps) => { }} > {!isExternal ? ( - {props.children} + + {props.children} + ) : ( {props.children} )} - ); + ) } export const SuggestionBox = (props: SuggestionBoxProps) => { @@ -59,14 +63,13 @@ export const SuggestionBox = (props: SuggestionBoxProps) => { flexDirection: props.size == 'large' ? 'column' : 'row', width: 'fit-content', borderRadius: '5px', - background: props.background ?? '$thBackground3', - fontSize: '15px', + fontSize: '18px', fontFamily: '$inter', fontWeight: '500', - color: '$thTextContrast', + color: '$grayText', px: '15px', - py: props.size == 'large' ? '15px' : '10px', - justifyContent: 'flex-start', + alignItems: 'center', + justifyContent: 'center', '@smDown': { flexDirection: 'column', alignItems: 'center', @@ -74,7 +77,7 @@ export const SuggestionBox = (props: SuggestionBoxProps) => { }, }} > - + {props.dismissible && ( { { }} > <>{suggestion.text} - + {props.showArrow && ( + + )} ) diff --git a/packages/web/components/templates/homeFeed/EmptyLibrary.tsx b/packages/web/components/templates/homeFeed/EmptyLibrary.tsx index 23dfe3d7b..696973857 100644 --- a/packages/web/components/templates/homeFeed/EmptyLibrary.tsx +++ b/packages/web/components/templates/homeFeed/EmptyLibrary.tsx @@ -3,8 +3,10 @@ import { useMemo } from 'react' import { LIBRARY_LEFT_MENU_WIDTH } from './LibraryFilterMenu' import { LayoutType } from './HomeFeedContainer' import { SuggestionBox, SuggestionAction } from '../../elements/SuggestionBox' +import { ErrorSlothIcon } from '../../elements/icons/ErrorSlothIcon' type EmptyLibraryProps = { + isError: boolean searchTerm: string | undefined onAddLinkClicked: () => void @@ -26,10 +28,14 @@ type MessageType = type HelpMessageProps = { type: MessageType + isError: boolean } export const ErrorBox = (props: HelpMessageProps) => { const errorTitle = useMemo(() => { + if (props.isError) { + return 'An error occurred' + } switch (props.type) { case 'inbox': return 'Your inbox is empty. The inbox will contain all your non-archived saved items.' @@ -60,12 +66,10 @@ export const ErrorBox = (props: HelpMessageProps) => { css={{ width: 'fit-content', borderRadius: '5px', - background: 'rgba(255, 59, 48, 0.3)', - fontSize: '15px', + fontSize: '25px', fontFamily: '$inter', - fontWeight: '500', + fontWeight: '700', color: '$thTextContrast', - py: '10px', px: '15px', '@smDown': { width: '100%', @@ -73,6 +77,7 @@ export const ErrorBox = (props: HelpMessageProps) => { '@xlgDown': { justifyContent: 'flex-start', }, + alignItems: 'center', }} > {errorTitle} @@ -87,6 +92,17 @@ type SuggestionMessage = { export const Suggestion = (props: HelpMessageProps) => { const helpMessage = useMemo(() => { + if (props.isError) { + return { + message: 'Something went wrong searching your library', + actions: [ + { + text: 'Join our Discord to get help', + url: 'https://discord.gg/h2z5rppzz9', + }, + ], + } + } switch (props.type) { case 'feed': return { @@ -151,6 +167,7 @@ export const Suggestion = (props: HelpMessageProps) => { <> {helpMessage ? ( @@ -194,13 +211,16 @@ export const EmptyLibrary = (props: EmptyLibraryProps) => { { }, }} > - - + {props.isError && } + + ) } diff --git a/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx b/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx index 01da20762..c738728f6 100644 --- a/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx +++ b/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx @@ -111,6 +111,7 @@ export function HomeFeedContainer(): JSX.Element { size, setSize, isValidating, + itemsDataError, performActionOnItem, mutate, } = useGetLibraryItemsQuery(queryInputs) @@ -128,6 +129,12 @@ export function HomeFeedContainer(): JSX.Element { } }, [mutate]) + useMemo(() => { + if (itemsDataError) { + console.log('search error: ', itemsDataError) + } + }, [itemsDataError]) + useEffect(() => { if (queryValue.startsWith('#')) { debouncedFetchSearchResults( @@ -854,6 +861,7 @@ export function HomeFeedContainer(): JSX.Element { hasMore={hasMore} hasData={!!itemsPages} totalItems={itemsPages?.[0].search.pageInfo.totalCount || 0} + isError={!!itemsDataError} isValidating={isValidating} labelsTarget={labelsTarget} setLabelsTarget={setLabelsTarget} @@ -888,6 +896,7 @@ type HomeFeedContentProps = { hasMore: boolean hasData: boolean totalItems: number + isError: boolean isValidating: boolean loadMore: () => void labelsTarget: LibraryItem | undefined @@ -1064,6 +1073,7 @@ function LibraryItemsLayout(props: LibraryItemsLayoutProps): JSX.Element { > {!props.isValidating && props.items.length == 0 ? ( { diff --git a/packages/web/lib/networking/queries/useGetLibraryItemsQuery.tsx b/packages/web/lib/networking/queries/useGetLibraryItemsQuery.tsx index cddf3d6f4..4fe5d3ca2 100644 --- a/packages/web/lib/networking/queries/useGetLibraryItemsQuery.tsx +++ b/packages/web/lib/networking/queries/useGetLibraryItemsQuery.tsx @@ -246,6 +246,16 @@ export function useGetLibraryItemsQuery({ }, { revalidateFirstPage: false } ) + console.log( + 'data: ', + data, + 'size', + size, + 'isValidating', + isValidating, + 'error', + error + ) let responseError = error let responsePages = data as LibraryItemsData[] | undefined diff --git a/yarn.lock b/yarn.lock index 891ce9530..b6fa12ff9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5858,6 +5858,15 @@ "@sentry/types" "7.77.0" "@sentry/utils" "7.77.0" +"@sentry-internal/tracing@7.91.0": + version "7.91.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.91.0.tgz#fbb6e1e3383e1eeee08633384e004da73ac1c37d" + integrity sha512-JH5y6gs6BS0its7WF2DhySu7nkhPDfZcdpAXldxzIlJpqFkuwQKLU5nkYJpiIyZz1NHYYtW5aum2bV2oCOdDRA== + dependencies: + "@sentry/core" "7.91.0" + "@sentry/types" "7.91.0" + "@sentry/utils" "7.91.0" + "@sentry/browser@7.50.0": version "7.50.0" resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.50.0.tgz#16c995c336322c8aec65570f90f50288678004ec" @@ -5882,17 +5891,6 @@ proxy-from-env "^1.1.0" which "^2.0.2" -"@sentry/core@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" - integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== - dependencies: - "@sentry/hub" "5.30.0" - "@sentry/minimal" "5.30.0" - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" - "@sentry/core@7.50.0": version "7.50.0" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.50.0.tgz#88bc9cbfc0cb429a28489ece6f0be7a7006436c4" @@ -5910,14 +5908,13 @@ "@sentry/types" "7.77.0" "@sentry/utils" "7.77.0" -"@sentry/hub@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" - integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== +"@sentry/core@7.91.0": + version "7.91.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.91.0.tgz#229334d7f03dd5d90a17495e61ce4215ab730b2a" + integrity sha512-tu+gYq4JrTdrR+YSh5IVHF0fJi/Pi9y0HZ5H9HnYy+UMcXIotxf6hIEaC6ZKGeLWkGXffz2gKpQLe/g6vy/lPA== dependencies: - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" + "@sentry/types" "7.91.0" + "@sentry/utils" "7.91.0" "@sentry/integrations@7.50.0": version "7.50.0" @@ -5939,15 +5936,6 @@ "@sentry/utils" "7.77.0" localforage "^1.8.1" -"@sentry/minimal@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" - integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== - dependencies: - "@sentry/hub" "5.30.0" - "@sentry/types" "5.30.0" - tslib "^1.9.3" - "@sentry/nextjs@^7.42.0": version "7.50.0" resolved "https://registry.yarnpkg.com/@sentry/nextjs/-/nextjs-7.50.0.tgz#b9e7727c8f974644bb84a01f40a0adedb44ec416" @@ -5991,20 +5979,16 @@ "@sentry/utils" "7.77.0" https-proxy-agent "^5.0.0" -"@sentry/node@^5.26.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" - integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== +"@sentry/node@^7.10.0": + version "7.91.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.91.0.tgz#26bf13c3daf988f9725afd1a3cc38ba2ff90d62a" + integrity sha512-hTIfSQxD7L+AKIqyjoq8CWBRkEQrrMZmA3GSZgPI5JFWBHgO0HBo5TH/8TU81oEJh6kqqHAl2ObMhmcnaFqlzg== dependencies: - "@sentry/core" "5.30.0" - "@sentry/hub" "5.30.0" - "@sentry/tracing" "5.30.0" - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - cookie "^0.4.1" + "@sentry-internal/tracing" "7.91.0" + "@sentry/core" "7.91.0" + "@sentry/types" "7.91.0" + "@sentry/utils" "7.91.0" https-proxy-agent "^5.0.0" - lru_map "^0.3.3" - tslib "^1.9.3" "@sentry/react@7.50.0": version "7.50.0" @@ -6038,28 +6022,12 @@ "@types/aws-lambda" "^8.10.62" "@types/express" "^4.17.14" -"@sentry/tracing@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" - integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== +"@sentry/tracing@^7.10.0": + version "7.91.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-7.91.0.tgz#2019542a9ed991c04a1f5e685a245b0fb8d69be1" + integrity sha512-IlSAMvqfCL/2TwwN4Tmk6bGMgilGruv5oIJ1GMenVZk53bHwjpjzMbd0ms8+S5zJwAgTQXoCbRhaFFrNmptteQ== dependencies: - "@sentry/hub" "5.30.0" - "@sentry/minimal" "5.30.0" - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" - -"@sentry/tracing@^7.9.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-7.77.0.tgz#39d7c30834f503fe9eb20ce1c8c8bd28f7d7c9ce" - integrity sha512-zr6eSCW3NJ124uj4Fy/6hh77cziy43dpYE1WpgvO/yhl1+kdrY2XVJ0bXGqwHU0KBm/eSgHD7yecUxmZUXiabA== - dependencies: - "@sentry-internal/tracing" "7.77.0" - -"@sentry/types@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" - integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== + "@sentry-internal/tracing" "7.91.0" "@sentry/types@7.50.0": version "7.50.0" @@ -6071,13 +6039,10 @@ resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.77.0.tgz#c5d00fe547b89ccde59cdea59143bf145cee3144" integrity sha512-nfb00XRJVi0QpDHg+JkqrmEBHsqBnxJu191Ded+Cs1OJ5oPXEW6F59LVcBScGvMqe+WEk1a73eH8XezwfgrTsA== -"@sentry/utils@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" - integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== - dependencies: - "@sentry/types" "5.30.0" - tslib "^1.9.3" +"@sentry/types@7.91.0": + version "7.91.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.91.0.tgz#5b68954e08986fecb0d4bef168df58eef62c32c7" + integrity sha512-bcQnb7J3P3equbCUc+sPuHog2Y47yGD2sCkzmnZBjvBT0Z1B4f36fI/5WjyZhTjLSiOdg3F2otwvikbMjmBDew== "@sentry/utils@7.50.0": version "7.50.0" @@ -6094,6 +6059,13 @@ dependencies: "@sentry/types" "7.77.0" +"@sentry/utils@7.91.0": + version "7.91.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.91.0.tgz#3b1a94c053c885877908cd3e1365e3d23e21a73f" + integrity sha512-fvxjrEbk6T6Otu++Ax9ntlQ0sGRiwSC179w68aC3u26Wr30FAIRKqHTCCdc2jyWk7Gd9uWRT/cq+g8NG/8BfSg== + dependencies: + "@sentry/types" "7.91.0" + "@sentry/webpack-plugin@1.20.0": version "1.20.0" resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-1.20.0.tgz#e7add76122708fb6b4ee7951294b521019720e58" From 67bc196496deaa32a810a6ebb9a1947913ae4c95 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 2 Jan 2024 17:25:01 +0800 Subject: [PATCH 3/5] Simpler loading view when loading from the refresh button --- .../App/Views/Home/HomeFeedViewIOS.swift | 22 ++++++++++++++++--- .../App/Views/Home/HomeFeedViewModel.swift | 14 ++++++++---- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift index 27cd7e70c..24b1c6b61 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift @@ -91,7 +91,7 @@ struct EmptyState: View { Text("You are all caught up.").foregroundColor(Color.extensionTextSubtle) Button(action: { Task { - await viewModel.loadItems(dataService: dataService, isRefresh: true) + await viewModel.loadItems(dataService: dataService, isRefresh: true, loadingBarStyle: .simple) } }, label: { Text("Refresh").bold() }) .foregroundColor(Color.blue) @@ -790,8 +790,16 @@ struct AnimatingCellHeight: AnimatableModifier { } } - if viewModel.showLoadingBar { + if viewModel.showLoadingBar == .redacted { redactedItems + } else if viewModel.showLoadingBar == .simple { + VStack { + ProgressView() + } + .frame(minHeight: 400) + .frame(maxWidth: .infinity) + .padding() + .listRowSeparator(.hidden, edges: .all) } else if viewModel.fetcher.items.isEmpty { EmptyState(viewModel: viewModel) .listRowSeparator(.hidden, edges: .all) @@ -951,13 +959,21 @@ struct AnimatingCellHeight: AnimatableModifier { ScrollView { LazyVGrid(columns: [GridItem(.adaptive(minimum: 325, maximum: 400), spacing: 16)], alignment: .center, spacing: 30) { - if viewModel.showLoadingBar { + if viewModel.showLoadingBar == .redacted { ForEach(fakeLibraryItems(dataService: dataService), id: \.id) { item in GridCard(item: item) .aspectRatio(1.0, contentMode: .fill) .background(Color.systemBackground) .cornerRadius(6) }.redacted(reason: .placeholder) + } else if viewModel.showLoadingBar == .simple { + VStack { + ProgressView() + } + .frame(minHeight: 400) + .frame(maxWidth: .infinity) + .padding() + .listRowSeparator(.hidden, edges: .all) } else { if !viewModel.fetcher.items.isEmpty { ForEach(Array(viewModel.fetcher.items.enumerated()), id: \.1.id) { idx, item in diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewModel.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewModel.swift index 6cc43df1c..9f89b307b 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewModel.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewModel.swift @@ -5,6 +5,12 @@ import SwiftUI import Utils import Views +enum LoadingBarStyle { + case none + case redacted + case simple +} + @MainActor final class HomeFeedViewModel: NSObject, ObservableObject { let filterKey: String @ObservedObject var fetcher: LibraryItemFetcher @@ -16,7 +22,7 @@ import Views @Published var itemForHighlightsView: Models.LibraryItem? @Published var linkRequest: LinkRequest? @Published var presentWebContainer = false - @Published var showLoadingBar = true + @Published var showLoadingBar = LoadingBarStyle.redacted @Published var selectedItem: Models.LibraryItem? @Published var linkIsActive = false @@ -194,9 +200,9 @@ import Views } } - func loadItems(dataService: DataService, isRefresh: Bool, forceRemote: Bool = false) async { + func loadItems(dataService: DataService, isRefresh: Bool, forceRemote: Bool = false, loadingBarStyle: LoadingBarStyle? = nil) async { isLoading = true - showLoadingBar = isRefresh + showLoadingBar = isRefresh ? loadingBarStyle ?? .redacted : .none if let filterState = filterState { await fetcher.loadItems( @@ -208,7 +214,7 @@ import Views } isLoading = false - showLoadingBar = false + showLoadingBar = .none } func loadFeatureItems(context: NSManagedObjectContext, predicate: NSPredicate, sort: NSSortDescriptor) async -> [Models.LibraryItem] { From 3806e971d32614ceb9220cec25b4cd88c10e7e59 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 2 Jan 2024 18:11:39 +0800 Subject: [PATCH 4/5] Revert some local changes to API --- packages/api/package.json | 6 +++--- packages/api/src/apollo.ts | 2 +- packages/api/src/sentry.ts | 30 +++++++++++++++--------------- packages/api/src/server.ts | 8 ++++---- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/packages/api/package.json b/packages/api/package.json index f1ff40840..34d9b24fb 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -39,8 +39,8 @@ "@opentelemetry/tracing": "^0.24.0", "@sendgrid/mail": "^7.6.0", "@sentry/integrations": "^7.10.0", - "@sentry/node": "^6.10.0", - "@sentry/tracing": "^7.10.0", + "@sentry/node": "^5.26.0", + "@sentry/tracing": "^7.9.0", "addressparser": "^1.0.1", "analytics-node": "^6.0.0", "apollo-datasource": "^3.3.1", @@ -151,4 +151,4 @@ "volta": { "extends": "../../package.json" } -} \ No newline at end of file +} diff --git a/packages/api/src/apollo.ts b/packages/api/src/apollo.ts index d7c29c441..7d4c8ea02 100644 --- a/packages/api/src/apollo.ts +++ b/packages/api/src/apollo.ts @@ -102,7 +102,7 @@ export function makeApolloServer(): ApolloServer { context: contextFunc, formatError: (err) => { logger.info('server error', err) - // Sentry.captureException(err) + Sentry.captureException(err) // hide error messages from frontend on prod return new Error('Unexpected server error') }, diff --git a/packages/api/src/sentry.ts b/packages/api/src/sentry.ts index d31f0b6ad..ac9bbc10d 100644 --- a/packages/api/src/sentry.ts +++ b/packages/api/src/sentry.ts @@ -2,18 +2,18 @@ import { env } from './env' import * as Sentry from '@sentry/node' import { CaptureConsole } from '@sentry/integrations' -// export const sentryConfig = { -// dsn: env.sentry.dsn, -// environment: env.server.apiEnv, -// // Don't bother collecting and sending events locally (reduces overhead). -// enabled: !env.dev.isLocal, -// serverName: process.env.GAE_INSTANCE || '', -// integrations: [ -// new Sentry.Integrations.OnUncaughtException(), -// new CaptureConsole({ levels: ['error'] }), -// ], -// debug: (env.dev.isLocal && process.env.DEBUG === 'true') || false, -// // We recommend adjusting this value in production, or using tracesSampler -// // for finer control -// tracesSampleRate: 0, -// } +export const sentryConfig = { + dsn: env.sentry.dsn, + environment: env.server.apiEnv, + // Don't bother collecting and sending events locally (reduces overhead). + enabled: !env.dev.isLocal, + serverName: process.env.GAE_INSTANCE || '', + integrations: [ + new Sentry.Integrations.OnUncaughtException(), + new CaptureConsole({ levels: ['error'] }), + ], + debug: (env.dev.isLocal && process.env.DEBUG === 'true') || false, + // We recommend adjusting this value in production, or using tracesSampler + // for finer control + tracesSampleRate: 0, +} diff --git a/packages/api/src/server.ts b/packages/api/src/server.ts index 584cd03bd..1bb75a085 100755 --- a/packages/api/src/server.ts +++ b/packages/api/src/server.ts @@ -36,7 +36,7 @@ import { userServiceRouter } from './routers/svc/user' import { webhooksServiceRouter } from './routers/svc/webhooks' import { textToSpeechRouter } from './routers/text_to_speech' import { userRouter } from './routers/user_router' -// import { sentryConfig } from './sentry' +import { sentryConfig } from './sentry' import { getClaimsByToken, getTokenByRequest, @@ -56,9 +56,9 @@ export const createApp = (): { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - // Sentry.init(sentryConfig) - // app.use(Sentry.Handlers.requestHandler()) - // app.use(Sentry.Handlers.tracingHandler()) + Sentry.init(sentryConfig) + app.use(Sentry.Handlers.requestHandler()) + app.use(Sentry.Handlers.tracingHandler()) app.use(cookieParser()) app.use(json({ limit: '100mb' })) From 67dee5b23f4ef075bdf66d85a0c94fa2516f3824 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 2 Jan 2024 18:14:19 +0800 Subject: [PATCH 5/5] Revert local changes to yarn.lock and web components --- .../web/components/elements/SuggestionBox.tsx | 32 +++--- .../templates/homeFeed/EmptyLibrary.tsx | 35 ++---- .../templates/homeFeed/HomeFeedContainer.tsx | 10 -- .../queries/useGetLibraryItemsQuery.tsx | 10 -- yarn.lock | 106 +++++++++++------- 5 files changed, 87 insertions(+), 106 deletions(-) diff --git a/packages/web/components/elements/SuggestionBox.tsx b/packages/web/components/elements/SuggestionBox.tsx index 2ed2af4bf..5118708af 100644 --- a/packages/web/components/elements/SuggestionBox.tsx +++ b/packages/web/components/elements/SuggestionBox.tsx @@ -14,7 +14,6 @@ export type SuggestionAction = { type SuggestionBoxProps = { helpMessage: string suggestions: SuggestionAction[] - isError: boolean size?: 'large' | 'small' background?: string @@ -26,7 +25,6 @@ type SuggestionBoxProps = { type InternalOrExternalLinkProps = { link: string children: ReactNode - showArrow: boolean } const InternalOrExternalLink = (props: InternalOrExternalLinkProps) => { @@ -42,16 +40,14 @@ const InternalOrExternalLink = (props: InternalOrExternalLinkProps) => { }} > {!isExternal ? ( - - {props.children} - + {props.children} ) : ( {props.children} )} - ) + ); } export const SuggestionBox = (props: SuggestionBoxProps) => { @@ -63,13 +59,14 @@ export const SuggestionBox = (props: SuggestionBoxProps) => { flexDirection: props.size == 'large' ? 'column' : 'row', width: 'fit-content', borderRadius: '5px', - fontSize: '18px', + background: props.background ?? '$thBackground3', + fontSize: '15px', fontFamily: '$inter', fontWeight: '500', - color: '$grayText', + color: '$thTextContrast', px: '15px', - alignItems: 'center', - justifyContent: 'center', + py: props.size == 'large' ? '15px' : '10px', + justifyContent: 'flex-start', '@smDown': { flexDirection: 'column', alignItems: 'center', @@ -77,7 +74,7 @@ export const SuggestionBox = (props: SuggestionBoxProps) => { }, }} > - + {props.dismissible && ( { { }} > <>{suggestion.text} - {props.showArrow && ( - - )} + ) diff --git a/packages/web/components/templates/homeFeed/EmptyLibrary.tsx b/packages/web/components/templates/homeFeed/EmptyLibrary.tsx index 696973857..23dfe3d7b 100644 --- a/packages/web/components/templates/homeFeed/EmptyLibrary.tsx +++ b/packages/web/components/templates/homeFeed/EmptyLibrary.tsx @@ -3,10 +3,8 @@ import { useMemo } from 'react' import { LIBRARY_LEFT_MENU_WIDTH } from './LibraryFilterMenu' import { LayoutType } from './HomeFeedContainer' import { SuggestionBox, SuggestionAction } from '../../elements/SuggestionBox' -import { ErrorSlothIcon } from '../../elements/icons/ErrorSlothIcon' type EmptyLibraryProps = { - isError: boolean searchTerm: string | undefined onAddLinkClicked: () => void @@ -28,14 +26,10 @@ type MessageType = type HelpMessageProps = { type: MessageType - isError: boolean } export const ErrorBox = (props: HelpMessageProps) => { const errorTitle = useMemo(() => { - if (props.isError) { - return 'An error occurred' - } switch (props.type) { case 'inbox': return 'Your inbox is empty. The inbox will contain all your non-archived saved items.' @@ -66,10 +60,12 @@ export const ErrorBox = (props: HelpMessageProps) => { css={{ width: 'fit-content', borderRadius: '5px', - fontSize: '25px', + background: 'rgba(255, 59, 48, 0.3)', + fontSize: '15px', fontFamily: '$inter', - fontWeight: '700', + fontWeight: '500', color: '$thTextContrast', + py: '10px', px: '15px', '@smDown': { width: '100%', @@ -77,7 +73,6 @@ export const ErrorBox = (props: HelpMessageProps) => { '@xlgDown': { justifyContent: 'flex-start', }, - alignItems: 'center', }} > {errorTitle} @@ -92,17 +87,6 @@ type SuggestionMessage = { export const Suggestion = (props: HelpMessageProps) => { const helpMessage = useMemo(() => { - if (props.isError) { - return { - message: 'Something went wrong searching your library', - actions: [ - { - text: 'Join our Discord to get help', - url: 'https://discord.gg/h2z5rppzz9', - }, - ], - } - } switch (props.type) { case 'feed': return { @@ -167,7 +151,6 @@ export const Suggestion = (props: HelpMessageProps) => { <> {helpMessage ? ( @@ -211,16 +194,13 @@ export const EmptyLibrary = (props: EmptyLibraryProps) => { { }, }} > - {props.isError && } - - + + ) } diff --git a/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx b/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx index c738728f6..01da20762 100644 --- a/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx +++ b/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx @@ -111,7 +111,6 @@ export function HomeFeedContainer(): JSX.Element { size, setSize, isValidating, - itemsDataError, performActionOnItem, mutate, } = useGetLibraryItemsQuery(queryInputs) @@ -129,12 +128,6 @@ export function HomeFeedContainer(): JSX.Element { } }, [mutate]) - useMemo(() => { - if (itemsDataError) { - console.log('search error: ', itemsDataError) - } - }, [itemsDataError]) - useEffect(() => { if (queryValue.startsWith('#')) { debouncedFetchSearchResults( @@ -861,7 +854,6 @@ export function HomeFeedContainer(): JSX.Element { hasMore={hasMore} hasData={!!itemsPages} totalItems={itemsPages?.[0].search.pageInfo.totalCount || 0} - isError={!!itemsDataError} isValidating={isValidating} labelsTarget={labelsTarget} setLabelsTarget={setLabelsTarget} @@ -896,7 +888,6 @@ type HomeFeedContentProps = { hasMore: boolean hasData: boolean totalItems: number - isError: boolean isValidating: boolean loadMore: () => void labelsTarget: LibraryItem | undefined @@ -1073,7 +1064,6 @@ function LibraryItemsLayout(props: LibraryItemsLayoutProps): JSX.Element { > {!props.isValidating && props.items.length == 0 ? ( { diff --git a/packages/web/lib/networking/queries/useGetLibraryItemsQuery.tsx b/packages/web/lib/networking/queries/useGetLibraryItemsQuery.tsx index 4fe5d3ca2..cddf3d6f4 100644 --- a/packages/web/lib/networking/queries/useGetLibraryItemsQuery.tsx +++ b/packages/web/lib/networking/queries/useGetLibraryItemsQuery.tsx @@ -246,16 +246,6 @@ export function useGetLibraryItemsQuery({ }, { revalidateFirstPage: false } ) - console.log( - 'data: ', - data, - 'size', - size, - 'isValidating', - isValidating, - 'error', - error - ) let responseError = error let responsePages = data as LibraryItemsData[] | undefined diff --git a/yarn.lock b/yarn.lock index b6fa12ff9..891ce9530 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5858,15 +5858,6 @@ "@sentry/types" "7.77.0" "@sentry/utils" "7.77.0" -"@sentry-internal/tracing@7.91.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.91.0.tgz#fbb6e1e3383e1eeee08633384e004da73ac1c37d" - integrity sha512-JH5y6gs6BS0its7WF2DhySu7nkhPDfZcdpAXldxzIlJpqFkuwQKLU5nkYJpiIyZz1NHYYtW5aum2bV2oCOdDRA== - dependencies: - "@sentry/core" "7.91.0" - "@sentry/types" "7.91.0" - "@sentry/utils" "7.91.0" - "@sentry/browser@7.50.0": version "7.50.0" resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.50.0.tgz#16c995c336322c8aec65570f90f50288678004ec" @@ -5891,6 +5882,17 @@ proxy-from-env "^1.1.0" which "^2.0.2" +"@sentry/core@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" + integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + "@sentry/core@7.50.0": version "7.50.0" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.50.0.tgz#88bc9cbfc0cb429a28489ece6f0be7a7006436c4" @@ -5908,13 +5910,14 @@ "@sentry/types" "7.77.0" "@sentry/utils" "7.77.0" -"@sentry/core@7.91.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.91.0.tgz#229334d7f03dd5d90a17495e61ce4215ab730b2a" - integrity sha512-tu+gYq4JrTdrR+YSh5IVHF0fJi/Pi9y0HZ5H9HnYy+UMcXIotxf6hIEaC6ZKGeLWkGXffz2gKpQLe/g6vy/lPA== +"@sentry/hub@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" + integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== dependencies: - "@sentry/types" "7.91.0" - "@sentry/utils" "7.91.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" "@sentry/integrations@7.50.0": version "7.50.0" @@ -5936,6 +5939,15 @@ "@sentry/utils" "7.77.0" localforage "^1.8.1" +"@sentry/minimal@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" + integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/types" "5.30.0" + tslib "^1.9.3" + "@sentry/nextjs@^7.42.0": version "7.50.0" resolved "https://registry.yarnpkg.com/@sentry/nextjs/-/nextjs-7.50.0.tgz#b9e7727c8f974644bb84a01f40a0adedb44ec416" @@ -5979,16 +5991,20 @@ "@sentry/utils" "7.77.0" https-proxy-agent "^5.0.0" -"@sentry/node@^7.10.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.91.0.tgz#26bf13c3daf988f9725afd1a3cc38ba2ff90d62a" - integrity sha512-hTIfSQxD7L+AKIqyjoq8CWBRkEQrrMZmA3GSZgPI5JFWBHgO0HBo5TH/8TU81oEJh6kqqHAl2ObMhmcnaFqlzg== +"@sentry/node@^5.26.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" + integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== dependencies: - "@sentry-internal/tracing" "7.91.0" - "@sentry/core" "7.91.0" - "@sentry/types" "7.91.0" - "@sentry/utils" "7.91.0" + "@sentry/core" "5.30.0" + "@sentry/hub" "5.30.0" + "@sentry/tracing" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + cookie "^0.4.1" https-proxy-agent "^5.0.0" + lru_map "^0.3.3" + tslib "^1.9.3" "@sentry/react@7.50.0": version "7.50.0" @@ -6022,12 +6038,28 @@ "@types/aws-lambda" "^8.10.62" "@types/express" "^4.17.14" -"@sentry/tracing@^7.10.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-7.91.0.tgz#2019542a9ed991c04a1f5e685a245b0fb8d69be1" - integrity sha512-IlSAMvqfCL/2TwwN4Tmk6bGMgilGruv5oIJ1GMenVZk53bHwjpjzMbd0ms8+S5zJwAgTQXoCbRhaFFrNmptteQ== +"@sentry/tracing@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" + integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== dependencies: - "@sentry-internal/tracing" "7.91.0" + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/tracing@^7.9.0": + version "7.77.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-7.77.0.tgz#39d7c30834f503fe9eb20ce1c8c8bd28f7d7c9ce" + integrity sha512-zr6eSCW3NJ124uj4Fy/6hh77cziy43dpYE1WpgvO/yhl1+kdrY2XVJ0bXGqwHU0KBm/eSgHD7yecUxmZUXiabA== + dependencies: + "@sentry-internal/tracing" "7.77.0" + +"@sentry/types@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" + integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== "@sentry/types@7.50.0": version "7.50.0" @@ -6039,10 +6071,13 @@ resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.77.0.tgz#c5d00fe547b89ccde59cdea59143bf145cee3144" integrity sha512-nfb00XRJVi0QpDHg+JkqrmEBHsqBnxJu191Ded+Cs1OJ5oPXEW6F59LVcBScGvMqe+WEk1a73eH8XezwfgrTsA== -"@sentry/types@7.91.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.91.0.tgz#5b68954e08986fecb0d4bef168df58eef62c32c7" - integrity sha512-bcQnb7J3P3equbCUc+sPuHog2Y47yGD2sCkzmnZBjvBT0Z1B4f36fI/5WjyZhTjLSiOdg3F2otwvikbMjmBDew== +"@sentry/utils@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" + integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== + dependencies: + "@sentry/types" "5.30.0" + tslib "^1.9.3" "@sentry/utils@7.50.0": version "7.50.0" @@ -6059,13 +6094,6 @@ dependencies: "@sentry/types" "7.77.0" -"@sentry/utils@7.91.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.91.0.tgz#3b1a94c053c885877908cd3e1365e3d23e21a73f" - integrity sha512-fvxjrEbk6T6Otu++Ax9ntlQ0sGRiwSC179w68aC3u26Wr30FAIRKqHTCCdc2jyWk7Gd9uWRT/cq+g8NG/8BfSg== - dependencies: - "@sentry/types" "7.91.0" - "@sentry/webpack-plugin@1.20.0": version "1.20.0" resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-1.20.0.tgz#e7add76122708fb6b4ee7951294b521019720e58"