Browse Source

Feature: Mobile - Append current desktop view route when redirecting to mobile.

Dusan Vuckovic 2 years ago
parent
commit
eb8fcc4e2a

+ 20 - 0
app/assets/javascripts/app/controllers/_plugin/mobile_detection.coffee

@@ -0,0 +1,20 @@
+class App.MobileDetection extends App.Controller
+  constructor: ->
+    super
+
+    @autoRedirectToMobile()
+
+  @isMobile: ->
+    # TODO: Remove `mobile_frontend_enabled` check when this switch is not needed any more.
+    App.Config.get('mobile_frontend_enabled') and isMobile()
+
+  @isForcingDesktopView: ->
+    # TODO: Remove `mobile_frontend_enabled` check when this switch is not needed any more.
+    App.Config.get('mobile_frontend_enabled') and App.LocalStorage.get('forceDesktopApp', false)
+
+  autoRedirectToMobile: ->
+    # Automatically redirect to mobile view, if on mobile device and not forcing desktop view.
+    if App.MobileDetection.isMobile() and !App.MobileDetection.isForcingDesktopView()
+      @navigate '#mobile'
+
+App.Config.set('mobile_detection', App.MobileDetection, 'Plugins')

+ 5 - 7
app/assets/javascripts/app/controllers/login.coffee

@@ -91,13 +91,11 @@ class Login extends App.ControllerFullPage
     )
 
     @replaceWith App.view('login')(
-      item:           data
-      logoUrl:        @logoUrl()
-      auth_providers: auth_providers
-      public_links:   public_links
-
-      # TODO: Remove `mobile_frontend_enabled` check when this switch is not needed any more.
-      is_mobile: App.Config.get('mobile_frontend_enabled') && isMobile()
+      item:             data
+      logoUrl:          @logoUrl()
+      auth_providers:   auth_providers
+      public_links:     public_links
+      show_mobile_link: App.MobileDetection.isMobile() or App.MobileDetection.isForcingDesktopView()
     )
 
     # set focus to username or password

+ 18 - 6
app/assets/javascripts/app/controllers/mobile.coffee

@@ -10,18 +10,30 @@ class Mobile
       return
 
     @clearForceDesktopApp()
-
-    if window.history?
-      window.history.replaceState(null, null, '/mobile')
-
-    window.location.href = '/mobile'
+    @navigateToMobile()
 
   clearForceDesktopApp: ->
     if App.LocalStorage.get('forceDesktopApp', false)
       App.LocalStorage.delete('forceDesktopApp')
 
+  navigateToMobile: ->
+    target = '/mobile'
+
+    # Append the previous route to the target URL, if there is a history entry.
+    #   Mobile view will handle the internal redirection automatically.
+    if window.history?
+      history = App.Config.get('History')
+      oldLocation = history[history.length-2]
+
+      if oldLocation
+        target += "/#{oldLocation}"
+
+        window.history.replaceState(null, null, oldLocation)
+
+    window.location.href = target
+
 App.Config.set('mobile', Mobile, 'Routes')
 
-if isMobile()
+if isMobile() or App.LocalStorage.get('forceDesktopApp', false)
   # TODO: Remove `mobile_frontend_enabled` check when this switch is not needed any more.
   App.Config.set('Mobile', { prio: 1500, parent: '#current_user', name: __('Continue to mobile'), translate: true, target: '#mobile', setting: ['mobile_frontend_enabled'] }, 'NavBarRight')

+ 2 - 2
app/assets/javascripts/app/controllers/ticket_overview.coffee

@@ -83,7 +83,7 @@ class App.TicketOverview extends App.Controller
     # redirect to last overview if we got called in first level
     @view = params['view']
     if !@view && @viewLast
-      @navigate "ticket/view/#{@viewLast}", { hideCurrentLocationFromHistory: true }
+      @navigate "#ticket/view/#{@viewLast}", { hideCurrentLocationFromHistory: true }
       return
 
     # build nav bar
@@ -345,7 +345,7 @@ class Navbar extends App.Controller
     # redirect to first view
     if @activeState && !@view && !@vertical
       view = data[0].link
-      @navigate "ticket/view/#{view}", { hideCurrentLocationFromHistory: true }
+      @navigate "#ticket/view/#{view}", { hideCurrentLocationFromHistory: true }
       return
 
     # add new views

+ 1 - 1
app/assets/javascripts/app/views/login.jst.eco

@@ -117,7 +117,7 @@
         <% end %>
       </p>
     <% end %>
-    <% if @is_mobile: %>
+    <% if @show_mobile_link: %>
       <p>
         <a class="align-center" href="#mobile"><%- @T('Continue to mobile') %></a>
       </p>

+ 2 - 2
app/frontend/apps/mobile/pages/account/views/AccountOverview.vue

@@ -201,8 +201,8 @@ const { forceDesktop } = useForceDesktop()
       </template>
     </FormGroup>
 
-    <CommonSectionMenu>
-      <CommonSectionMenuItem v-if="hasVersionPermission" :label="__('Version')">
+    <CommonSectionMenu v-if="hasVersionPermission">
+      <CommonSectionMenuItem :label="__('Version')">
         {{
           $t('This is Zammad version %s', productAbout?.productAbout as string)
         }}

+ 1 - 0
app/frontend/apps/mobile/pages/ticket/routes.ts

@@ -46,6 +46,7 @@ const routes: RouteRecordRaw[] = [
     name: 'TicketOverview',
     props: true,
     component: () => import('./views/TicketOverview.vue'),
+    alias: '/ticket/view/:overviewLink?',
     meta: {
       title: __('Tickets'),
       requiresAuth: true,

+ 30 - 6
spec/system/apps/mobile/app_links_spec.rb

@@ -44,7 +44,7 @@ RSpec.describe 'Mobile > App links', app: :mobile, type: :system do
     end
 
     shared_examples 'redirecting to mobile app' do |source, target, authenticated: false|
-      it 'redirects to mobile app and does not remember the choice' do
+      it 'redirects to mobile app' do
         visit source, app: :desktop
 
         if authenticated
@@ -54,10 +54,6 @@ RSpec.describe 'Mobile > App links', app: :mobile, type: :system do
         click 'a', text: 'Continue to mobile'
 
         expect_current_route(target, app: :mobile)
-
-        visit source, app: :desktop
-
-        expect_current_route(source, app: :desktop)
       end
     end
 
@@ -72,13 +68,41 @@ RSpec.describe 'Mobile > App links', app: :mobile, type: :system do
     end
 
     context 'with mobile user agent', mobile_user_agent: true do
+      before do
+        visit '/'
+
+        # Force desktop view in order to circumvent the automatic redirection to mobile.
+        page.evaluate_script "window.localStorage.setItem('forceDesktopApp', true)"
+      end
+
       context 'when user is unauthenticated', authenticated_as: false do
         it_behaves_like 'redirecting to mobile app', 'login', 'login'
       end
 
       context 'when user is authenticated' do
-        it_behaves_like 'redirecting to mobile app', 'dashboard', '', authenticated: true
+        it_behaves_like 'redirecting to mobile app', 'profile', 'profile', authenticated: true
+        it_behaves_like 'redirecting to mobile app', 'profile/avatar', 'profile/avatar', authenticated: true
+        it_behaves_like 'redirecting to mobile app', 'organization/profile/1', 'organization/profile/1', authenticated: true
+        it_behaves_like 'redirecting to mobile app', 'search/string', 'search/ticket?search=string', authenticated: true
+        it_behaves_like 'redirecting to mobile app', 'ticket/create', 'ticket/create', authenticated: true
+        it_behaves_like 'redirecting to mobile app', 'ticket/zoom/1', 'ticket/zoom/1', authenticated: true
+        it_behaves_like 'redirecting to mobile app', 'user/profile/1', 'user/profile/1', authenticated: true
+        it_behaves_like 'redirecting to mobile app', 'dashboard', '#dashboard', authenticated: true
+
+        context 'with customer user', authenticated_as: :customer do
+          let(:customer) { create(:customer) }
+
+          it_behaves_like 'redirecting to mobile app', 'ticket/view/my_tickets', 'ticket/view/my_tickets', authenticated: true
+        end
       end
     end
   end
+
+  context 'with mobile device detection', mobile_user_agent: true do
+    it 'automatically redirects to mobile app' do
+      visit '/', app: :desktop
+
+      expect_current_route('/', app: :mobile)
+    end
+  end
 end