Need Help with Zoomable Camera Image in f7-popup

Problem Description:

I’m working on a multi-camera widget with a fullscreen popup feature. The popup works perfectly, but I need the camera image to be zoomable (pinch-to-zoom) while maintaining automatic refresh.

Current Working Code:

# Current f7-popup implementation (works but NOT zoomable)
- component: f7-popup
  config:
    backdrop: true
    closeByBackdropClick: true
    closeByOutsideClick: true
    closeOnEscape: true
    id: fullscreenCamera
    opened: =vars.fullscreenOpen === 'true'
    style:
      background: black
      z-index: 10000
  slots:
    default:
      - component: f7-block
        config:
          style:
            align-items: center
            background: black
            display: flex
            height: 100vh
            justify-content: center
            margin: 0
            padding: 0
            position: relative
            width: 100vw
        slots:
          default:
            - component: oh-image-card
              config:
                item: "= vars.activeCamera === 1 || vars.activeCamera === undefined ?
                  props.camera1ImageItem : vars.activeCamera === 2 ?
                  props.camera2ImageItem : vars.activeCamera === 3 ?
                  props.camera3ImageItem : vars.activeCamera === 4 ?
                  props.camera4ImageItem : vars.activeCamera === 5 ?
                  props.camera5ImageItem : vars.activeCamera === 6 ?
                  props.camera6ImageItem : vars.activeCamera === 7 ?
                  props.camera7ImageItem : props.camera1ImageItem"
                noBorder: true
                noShadow: true
                refreshInterval: =props.refreshRate
                style:
                  background: transparent
                  height: 100%
                  object-fit: contain
                  width: 100%
            - component: oh-button
              config:
                action: variable
                actionVariable: fullscreenOpen
                actionVariableValue: "false"
                iconColor: red
                iconF7: xmark
                iconSize: 28
                style:
                  position: absolute
                  right: 0px
                  top: 0px
                  z-index: 10001

What I’ve Tried:

Attempt 1: Using f7-photo-browser with action: photos

# This approach makes image zoomable but NO refresh functionality
- component: oh-button
  config:
    action: photos
    actionPhotos:
      - "=items[vars.activeCamera === 1 ? props.camera1ImageItem : 
           vars.activeCamera === 2 ? props.camera2ImageItem : 
           props.camera1ImageItem].state"
    style:
      # button styles...

Result: :white_check_mark: Image is zoomable, :cross_mark: No automatic refresh (static image)

Attempt 2: Using f7-photo-browser component directly

# Tried embedding f7-photo-browser in popup
- component: f7-photo-browser
  config:
    photos:
      - "=items[props.camera1ImageItem].state"
    type: popup
    # other configs...

Result: :cross_mark: Doesn’t work as expected in widget context

Attempt 3: CSS transform for zoom

# Tried adding CSS transforms to oh-image-card
style:
  transform-origin: center
  transition: transform 0.3s ease
  # touch events don't work properly

Result: :cross_mark: No proper touch/pinch zoom support

Requirements:

  1. :white_check_mark: Zoomable image (pinch-to-zoom, pan when zoomed)
  2. :white_check_mark: Automatic refresh (e.g., every 1000ms)
  3. :white_check_mark: Fullscreen popup overlay
  4. :white_check_mark: Close button functionality
  5. :white_check_mark: Dynamic camera switching (7 different cameras)

Questions:

  1. Is there a way to make oh-image-card zoomable within f7-popup?
  2. Can f7-photo-browser be configured to auto-refresh images?
  3. Are there alternative approaches using other F7 components?
  4. CSS-only solutions that work with touch devices?

Any suggestions or working examples would be greatly appreciated!

and by the way here is the full actual code:

uid: CameraSnapshotHistory_auto_v3
tags: []
props:
  parameters:
    - label: Kamera 1 Equipment
      name: camera1
      required: false
      type: TEXT
    - label: Kamera 1 Name
      name: camera1Name
      required: false
      type: TEXT
    - label: Kamera 1 Base URL
      name: camera1BaseURL
      required: false
      type: TEXT
    - context: item
      label: Kamera 1 Image Item
      name: camera1ImageItem
      required: false
      type: TEXT
    - context: item
      label: Kamera 1 PTZ Preset Item
      name: camera1PtzPresetItem
      required: false
      type: TEXT
    - description: "Format: 1=Option1,2=Option2,3=Option3"
      label: Kamera 1 PTZ Preset Options
      name: camera1PtzPresetOptions
      required: false
      type: TEXT
    - context: item
      label: Kamera 1 PTZ Auto Reset Item
      name: camera1PtzAutoResetItem
      required: false
      type: TEXT
    - description: "Format: 1=Auto-Reset,2=Kamerafahrt,3=Manuell"
      label: Kamera 1 PTZ Auto Reset Options
      name: camera1PtzAutoResetOptions
      required: false
      type: TEXT
    - label: Kamera 2 Equipment
      name: camera2
      required: false
      type: TEXT
    - label: Kamera 2 Name
      name: camera2Name
      required: false
      type: TEXT
    - label: Kamera 2 Base URL
      name: camera2BaseURL
      required: false
      type: TEXT
    - context: item
      label: Kamera 2 Image Item
      name: camera2ImageItem
      required: false
      type: TEXT
    - context: item
      label: Kamera 2 PTZ Preset Item
      name: camera2PtzPresetItem
      required: false
      type: TEXT
    - description: "Format: 1=Option1,2=Option2,3=Option3"
      label: Kamera 2 PTZ Preset Options
      name: camera2PtzPresetOptions
      required: false
      type: TEXT
    - context: item
      label: Kamera 2 PTZ Auto Reset Item
      name: camera2PtzAutoResetItem
      required: false
      type: TEXT
    - description: "Format: 1=Auto-Reset,2=Kamerafahrt,3=Manuell"
      label: Kamera 2 PTZ Auto Reset Options
      name: camera2PtzAutoResetOptions
      required: false
      type: TEXT
    - label: Kamera 3 Equipment
      name: camera3
      required: false
      type: TEXT
    - label: Kamera 3 Name
      name: camera3Name
      required: false
      type: TEXT
    - label: Kamera 3 Base URL
      name: camera3BaseURL
      required: false
      type: TEXT
    - context: item
      label: Kamera 3 Image Item
      name: camera3ImageItem
      required: false
      type: TEXT
    - context: item
      label: Kamera 3 PTZ Preset Item
      name: camera3PtzPresetItem
      required: false
      type: TEXT
    - description: "Format: 1=Option1,2=Option2,3=Option3"
      label: Kamera 3 PTZ Preset Options
      name: camera3PtzPresetOptions
      required: false
      type: TEXT
    - context: item
      label: Kamera 3 PTZ Auto Reset Item
      name: camera3PtzAutoResetItem
      required: false
      type: TEXT
    - description: "Format: 1=Auto-Reset,2=Kamerafahrt,3=Manuell"
      label: Kamera 3 PTZ Auto Reset Options
      name: camera3PtzAutoResetOptions
      required: false
      type: TEXT
    - label: Kamera 4 Equipment
      name: camera4
      required: false
      type: TEXT
    - label: Kamera 4 Name
      name: camera4Name
      required: false
      type: TEXT
    - label: Kamera 4 Base URL
      name: camera4BaseURL
      required: false
      type: TEXT
    - context: item
      label: Kamera 4 Image Item
      name: camera4ImageItem
      required: false
      type: TEXT
    - context: item
      label: Kamera 4 PTZ Preset Item
      name: camera4PtzPresetItem
      required: false
      type: TEXT
    - description: "Format: 1=Option1,2=Option2,3=Option3"
      label: Kamera 4 PTZ Preset Options
      name: camera4PtzPresetOptions
      required: false
      type: TEXT
    - context: item
      label: Kamera 4 PTZ Auto Reset Item
      name: camera4PtzAutoResetItem
      required: false
      type: TEXT
    - description: "Format: 1=Auto-Reset,2=Kamerafahrt,3=Manuell"
      label: Kamera 4 PTZ Auto Reset Options
      name: camera4PtzAutoResetOptions
      required: false
      type: TEXT
    - label: Kamera 5 Equipment
      name: camera5
      required: false
      type: TEXT
    - label: Kamera 5 Name
      name: camera5Name
      required: false
      type: TEXT
    - label: Kamera 5 Base URL
      name: camera5BaseURL
      required: false
      type: TEXT
    - context: item
      label: Kamera 5 Image Item
      name: camera5ImageItem
      required: false
      type: TEXT
    - context: item
      label: Kamera 5 PTZ Preset Item
      name: camera5PtzPresetItem
      required: false
      type: TEXT
    - description: "Format: 1=Option1,2=Option2,3=Option3"
      label: Kamera 5 PTZ Preset Options
      name: camera5PtzPresetOptions
      required: false
      type: TEXT
    - context: item
      label: Kamera 5 PTZ Auto Reset Item
      name: camera5PtzAutoResetItem
      required: false
      type: TEXT
    - description: "Format: 1=Auto-Reset,2=Kamerafahrt,3=Manuell"
      label: Kamera 5 PTZ Auto Reset Options
      name: camera5PtzAutoResetOptions
      required: false
      type: TEXT
    - label: Kamera 6 Equipment
      name: camera6
      required: false
      type: TEXT
    - label: Kamera 6 Name
      name: camera6Name
      required: false
      type: TEXT
    - label: Kamera 6 Base URL
      name: camera6BaseURL
      required: false
      type: TEXT
    - context: item
      label: Kamera 6 Image Item
      name: camera6ImageItem
      required: false
      type: TEXT
    - context: item
      label: Kamera 6 PTZ Preset Item
      name: camera6PtzPresetItem
      required: false
      type: TEXT
    - description: "Format: 1=Option1,2=Option2,3=Option3"
      label: Kamera 6 PTZ Preset Options
      name: camera6PtzPresetOptions
      required: false
      type: TEXT
    - context: item
      label: Kamera 6 PTZ Auto Reset Item
      name: camera6PtzAutoResetItem
      required: false
      type: TEXT
    - description: "Format: 1=Auto-Reset,2=Kamerafahrt,3=Manuell"
      label: Kamera 6 PTZ Auto Reset Options
      name: camera6PtzAutoResetOptions
      required: false
      type: TEXT
    - label: Kamera 7 Equipment
      name: camera7
      required: false
      type: TEXT
    - label: Kamera 7 Name
      name: camera7Name
      required: false
      type: TEXT
    - label: Kamera 7 Base URL
      name: camera7BaseURL
      required: false
      type: TEXT
    - context: item
      label: Kamera 7 Image Item
      name: camera7ImageItem
      required: false
      type: TEXT
    - context: item
      label: Kamera 7 PTZ Preset Item
      name: camera7PtzPresetItem
      required: false
      type: TEXT
    - description: "Format: 1=Option1,2=Option2,3=Option3"
      label: Kamera 7 PTZ Preset Options
      name: camera7PtzPresetOptions
      required: false
      type: TEXT
    - context: item
      label: Kamera 7 PTZ Auto Reset Item
      name: camera7PtzAutoResetItem
      required: false
      type: TEXT
    - description: "Format: 1=Auto-Reset,2=Kamerafahrt,3=Manuell"
      label: Kamera 7 PTZ Auto Reset Options
      name: camera7PtzAutoResetOptions
      required: false
      type: TEXT
    - description: Refresh rate in milliseconds (e.g., 1000 for 1 second)
      label: Refresh Rate
      name: refreshRate
      required: true
      type: INTEGER
timestamp: Aug 11, 2025, 1:29:04 PM
component: f7-card
config:
  key: "=((vars.selected || 0) === undefined) ? Math.random() : Math.random() +
    (vars.selected || 0)"
  noBorder: true
  noShadow: true
  style:
    --f7-card-margin-horizontal: 5px
    --f7-card-margin-vertical: 5px
    background: var(--f7-theme-color)
    border-radius: var(--f7-card-expandable-border-radius)
    height: auto
    max-height: "=vars.ptzExpanded === 'true' && vars.archive !== 2 ? 'none' : 'auto'"
    overflow: hidden
    transition: all 0.3s ease
    width: auto
slots:
  default:
    - component: f7-block
      config:
        style:
          background: var(--f7-theme-color)
          border-radius: 0px
          color: "=(themeOptions.dark == 'dark') ? 'white' : 'black'"
          margin: 0
          padding: 8px
      slots:
        default:
          - component: f7-swiper
            config:
              params:
                direction: horizontal
                freeMode: true
                mousewheel: true
                scrollbar:
                  draggable: true
                  el: .swiper-scrollbar
                slidesPerView: auto
              style:
                height: 40px
            slots:
              default:
                - component: f7-swiper-slide
                  config:
                    style:
                      padding: 0 4px
                      width: auto
                    visible: =!!(props.camera1 && props.camera1Name)
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: variable
                          actionVariable: activeCamera
                          actionVariableValue: 1
                          style:
                            align-items: center
                            background: "=vars.activeCamera === 1 || vars.activeCamera === undefined ?
                              'var(--f7-theme-color-shade)' :
                              'rgba(255,255,255,0.2)'"
                            border: "=vars.activeCamera === 1 || vars.activeCamera === undefined ? '2px
                              solid white' : '1px solid rgba(255,255,255,0.3)'"
                            border-radius: 6px
                            color: white
                            display: flex
                            font-size: 13px
                            font-weight: "=vars.activeCamera === 1 || vars.activeCamera === undefined ?
                              'bold' : 'normal'"
                            justify-content: center
                            padding: 4px 8px
                            text-align: center
                          text: =props.camera1Name
                - component: f7-swiper-slide
                  config:
                    style:
                      padding: 0 4px
                      width: auto
                    visible: =!!(props.camera2 && props.camera2Name)
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: variable
                          actionVariable: activeCamera
                          actionVariableValue: 2
                          style:
                            align-items: center
                            background: "=vars.activeCamera === 2 ? 'var(--f7-theme-color-shade)' :
                              'rgba(255,255,255,0.2)'"
                            border: "=vars.activeCamera === 2 ? '2px solid white' : '1px solid
                              rgba(255,255,255,0.3)'"
                            border-radius: 6px
                            color: white
                            display: flex
                            font-size: 13px
                            font-weight: "=vars.activeCamera === 2 ? 'bold' : 'normal'"
                            justify-content: center
                            padding: 4px 8px
                            text-align: center
                          text: =props.camera2Name
                - component: f7-swiper-slide
                  config:
                    style:
                      padding: 0 4px
                      width: auto
                    visible: =!!(props.camera3 && props.camera3Name)
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: variable
                          actionVariable: activeCamera
                          actionVariableValue: 3
                          style:
                            align-items: center
                            background: "=vars.activeCamera === 3 ? 'var(--f7-theme-color-shade)' :
                              'rgba(255,255,255,0.2)'"
                            border: "=vars.activeCamera === 3 ? '2px solid white' : '1px solid
                              rgba(255,255,255,0.3)'"
                            border-radius: 6px
                            color: white
                            display: flex
                            font-size: 13px
                            font-weight: "=vars.activeCamera === 3 ? 'bold' : 'normal'"
                            justify-content: center
                            padding: 4px 8px
                            text-align: center
                          text: =props.camera3Name
                - component: f7-swiper-slide
                  config:
                    style:
                      padding: 0 4px
                      width: auto
                    visible: =!!(props.camera4 && props.camera4Name)
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: variable
                          actionVariable: activeCamera
                          actionVariableValue: 4
                          style:
                            align-items: center
                            background: "=vars.activeCamera === 4 ? 'var(--f7-theme-color-shade)' :
                              'rgba(255,255,255,0.2)'"
                            border: "=vars.activeCamera === 4 ? '2px solid white' : '1px solid
                              rgba(255,255,255,0.3)'"
                            border-radius: 6px
                            color: white
                            display: flex
                            font-size: 13px
                            font-weight: "=vars.activeCamera === 4 ? 'bold' : 'normal'"
                            justify-content: center
                            padding: 4px 8px
                            text-align: center
                          text: =props.camera4Name
                - component: f7-swiper-slide
                  config:
                    style:
                      padding: 0 4px
                      width: auto
                    visible: =!!(props.camera5 && props.camera5Name)
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: variable
                          actionVariable: activeCamera
                          actionVariableValue: 5
                          style:
                            align-items: center
                            background: "=vars.activeCamera === 5 ? 'var(--f7-theme-color-shade)' :
                              'rgba(255,255,255,0.2)'"
                            border: "=vars.activeCamera === 5 ? '2px solid white' : '1px solid
                              rgba(255,255,255,0.3)'"
                            border-radius: 6px
                            color: white
                            display: flex
                            font-size: 13px
                            font-weight: "=vars.activeCamera === 5 ? 'bold' : 'normal'"
                            justify-content: center
                            padding: 4px 8px
                            text-align: center
                          text: =props.camera5Name
                - component: f7-swiper-slide
                  config:
                    style:
                      padding: 0 4px
                      width: auto
                    visible: =!!(props.camera6 && props.camera6Name)
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: variable
                          actionVariable: activeCamera
                          actionVariableValue: 6
                          style:
                            align-items: center
                            background: "=vars.activeCamera === 6 ? 'var(--f7-theme-color-shade)' :
                              'rgba(255,255,255,0.2)'"
                            border: "=vars.activeCamera === 6 ? '2px solid white' : '1px solid
                              rgba(255,255,255,0.3)'"
                            border-radius: 6px
                            color: white
                            display: flex
                            font-size: 13px
                            font-weight: "=vars.activeCamera === 6 ? 'bold' : 'normal'"
                            justify-content: center
                            padding: 4px 8px
                            text-align: center
                          text: =props.camera6Name
                - component: f7-swiper-slide
                  config:
                    style:
                      padding: 0 4px
                      width: auto
                    visible: =!!(props.camera7 && props.camera7Name)
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: variable
                          actionVariable: activeCamera
                          actionVariableValue: 7
                          style:
                            align-items: center
                            background: "=vars.activeCamera === 7 ? 'var(--f7-theme-color-shade)' :
                              'rgba(255,255,255,0.2)'"
                            border: "=vars.activeCamera === 7 ? '2px solid white' : '1px solid
                              rgba(255,255,255,0.3)'"
                            border-radius: 6px
                            color: white
                            display: flex
                            font-size: 13px
                            font-weight: "=vars.activeCamera === 7 ? 'bold' : 'normal'"
                            justify-content: center
                            padding: 4px 8px
                            text-align: center
                          text: =props.camera7Name
    - component: f7-block
      config:
        style:
          background: transparent
          margin: 0
          overflow: hidden
          padding: 0
          position: relative
      slots:
        default:
          - component: oh-video-card
            config:
              hideControls: false
              noBorder: true
              noShadow: true
              startManually: false
              style:
                background: transparent
                border-radius: 0px
                display: block
                height: auto
                margin: 0px
                max-width: 100%
                object-fit: contain
                padding: 0px
                width: 100%
              url: "= (vars.activeCamera === 1 || vars.activeCamera === undefined ?
                props.camera1BaseURL : vars.activeCamera === 2 ?
                props.camera2BaseURL : vars.activeCamera === 3 ?
                props.camera3BaseURL : vars.activeCamera === 4 ?
                props.camera4BaseURL : vars.activeCamera === 5 ?
                props.camera5BaseURL : vars.activeCamera === 6 ?
                props.camera6BaseURL : vars.activeCamera === 7 ?
                props.camera7BaseURL : props.camera1BaseURL) +
                items[(vars.activeCamera === 1 || vars.activeCamera ===
                undefined ? props.camera1 : vars.activeCamera === 2 ?
                props.camera2 : vars.activeCamera === 3 ? props.camera3 :
                vars.activeCamera === 4 ? props.camera4 : vars.activeCamera ===
                5 ? props.camera5 : vars.activeCamera === 6 ? props.camera6 :
                vars.activeCamera === 7 ? props.camera7 : props.camera1) +
                '_MP4_History'].state.split(',')[(vars.selected || 0)] + '.mp4'"
              visible: =vars.archive == 2
          - component: oh-image-card
            config:
              item: "= vars.activeCamera === 1 || vars.activeCamera === undefined ?
                props.camera1ImageItem : vars.activeCamera === 2 ?
                props.camera2ImageItem : vars.activeCamera === 3 ?
                props.camera3ImageItem : vars.activeCamera === 4 ?
                props.camera4ImageItem : vars.activeCamera === 5 ?
                props.camera5ImageItem : vars.activeCamera === 6 ?
                props.camera6ImageItem : vars.activeCamera === 7 ?
                props.camera7ImageItem : props.camera1ImageItem"
              noBorder: true
              noShadow: true
              refreshInterval: "=vars.fullscreenOpen === 'true' ? 0 : props.refreshRate"
              style:
                background: transparent
                border-radius: 0px
                display: block
                height: auto
                margin: 0px
                max-width: 100%
                object-fit: contain
                padding: 0px
                width: 100%
              visible: =vars.archive != 2
          - component: f7-row
            config:
              class: no-gap
              noBorder: true
              noShadow: true
              style:
                height: auto
                position: absolute
                top: 0px
                width: 100%
                z-index: 2
            slots:
              default:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: archive
                    actionVariableValue: 2
                    iconColor: red
                    iconF7: folder
                    iconSize: 28
                    style:
                      margin: -2px
                    visible: "= items[(vars.activeCamera === 1 || vars.activeCamera === undefined ?
                      props.camera1 : vars.activeCamera === 2 ? props.camera2 :
                      vars.activeCamera === 3 ? props.camera3 :
                      vars.activeCamera === 4 ? props.camera4 :
                      vars.activeCamera === 5 ? props.camera5 :
                      vars.activeCamera === 6 ? props.camera6 :
                      vars.activeCamera === 7 ? props.camera7 : props.camera1) +
                      '_MP4_History'].state !== NULL && items[(vars.activeCamera
                      === 1 || vars.activeCamera === undefined ? props.camera1 :
                      vars.activeCamera === 2 ? props.camera2 :
                      vars.activeCamera === 3 ? props.camera3 :
                      vars.activeCamera === 4 ? props.camera4 :
                      vars.activeCamera === 5 ? props.camera5 :
                      vars.activeCamera === 6 ? props.camera6 :
                      vars.activeCamera === 7 ? props.camera7 : props.camera1) +
                      '_MP4_History_Length'].state > 0 ? vars.archive !== 2 :
                      false"
                    z-index: 2
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: fullscreenOpen
                    actionVariableValue: "true"
                    iconColor: red
                    iconF7: viewfinder
                    iconSize: 28
                    style:
                      height: 32px
                      margin: -2px
                      position: absolute
                      right: 0px
                      top: 0px
                      width: 32px
                      z-index: 2
                    visible: =vars.archive !== 2
                - component: Label
                  config:
                    style:
                      color: red
                      font-size: 9px
                      left: 14px
                      position: absolute
                      top: 6px
                      z-index: -1
                    text: =((vars.selected || 0)+1)
                    visible: =vars.archive == 2
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: archive
                    actionVariableValue: 1
                    iconColor: red
                    iconF7: videocam
                    iconSize: 28
                    style:
                      margin: -2px
                    visible: =(vars.archive == 2)
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: selected
                    actionVariableValue: "= items[(vars.activeCamera === 1 || vars.activeCamera ===
                      undefined ? props.camera1 : vars.activeCamera === 2 ?
                      props.camera2 : vars.activeCamera === 3 ? props.camera3 :
                      vars.activeCamera === 4 ? props.camera4 :
                      vars.activeCamera === 5 ? props.camera5 :
                      vars.activeCamera === 6 ? props.camera6 :
                      vars.activeCamera === 7 ? props.camera7 : props.camera1) +
                      '_MP4_History_Length'].state - 1"
                    iconColor: red
                    iconF7: backward_end
                    iconSize: 28
                    style:
                      margin: -2px
                    visible: "=vars.archive == 2 && items[(vars.activeCamera === 1 ||
                      vars.activeCamera === undefined ? props.camera1 :
                      vars.activeCamera === 2 ? props.camera2 :
                      vars.activeCamera === 3 ? props.camera3 :
                      vars.activeCamera === 4 ? props.camera4 :
                      vars.activeCamera === 5 ? props.camera5 :
                      vars.activeCamera === 6 ? props.camera6 :
                      vars.activeCamera === 7 ? props.camera7 : props.camera1) +
                      '_MP4_History_Length'].state > 0"
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: selected
                    actionVariableValue: "=((vars.selected || 0)+1 < items[(vars.activeCamera === 1
                      || vars.activeCamera === undefined ? props.camera1 :
                      vars.activeCamera === 2 ? props.camera2 :
                      vars.activeCamera === 3 ? props.camera3 :
                      vars.activeCamera === 4 ? props.camera4 :
                      vars.activeCamera === 5 ? props.camera5 :
                      vars.activeCamera === 6 ? props.camera6 :
                      vars.activeCamera === 7 ? props.camera7 : props.camera1) +
                      '_MP4_History_Length'].state)?((vars.selected || 0)+1):(
                      items[(vars.activeCamera === 1 || vars.activeCamera ===
                      undefined ? props.camera1 : vars.activeCamera === 2 ?
                      props.camera2 : vars.activeCamera === 3 ? props.camera3 :
                      vars.activeCamera === 4 ? props.camera4 :
                      vars.activeCamera === 5 ? props.camera5 :
                      vars.activeCamera === 6 ? props.camera6 :
                      vars.activeCamera === 7 ? props.camera7 : props.camera1) +
                      '_MP4_History_Length'].state-1)"
                    iconColor: red
                    iconF7: arrowtriangle_left
                    iconSize: 28
                    style:
                      margin: -2px
                    visible: "=vars.archive == 2 && items[(vars.activeCamera === 1 ||
                      vars.activeCamera === undefined ? props.camera1 :
                      vars.activeCamera === 2 ? props.camera2 :
                      vars.activeCamera === 3 ? props.camera3 :
                      vars.activeCamera === 4 ? props.camera4 :
                      vars.activeCamera === 5 ? props.camera5 :
                      vars.activeCamera === 6 ? props.camera6 :
                      vars.activeCamera === 7 ? props.camera7 : props.camera1) +
                      '_MP4_History_Length'].state > 0"
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: selected
                    actionVariableValue: =((vars.selected || 0) != 0)?((vars.selected || 0)-1):(0)
                    iconColor: red
                    iconF7: arrowtriangle_right
                    iconSize: 28
                    style:
                      margin: -2px
                    visible: "=vars.archive == 2 && items[(vars.activeCamera === 1 ||
                      vars.activeCamera === undefined ? props.camera1 :
                      vars.activeCamera === 2 ? props.camera2 :
                      vars.activeCamera === 3 ? props.camera3 :
                      vars.activeCamera === 4 ? props.camera4 :
                      vars.activeCamera === 5 ? props.camera5 :
                      vars.activeCamera === 6 ? props.camera6 :
                      vars.activeCamera === 7 ? props.camera7 : props.camera1) +
                      '_MP4_History_Length'].state > 0"
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: selected
                    actionVariableValue: 0
                    iconColor: red
                    iconF7: forward_end
                    iconSize: 28
                    style:
                      margin: -2px
                    visible: "=vars.archive == 2 && items[(vars.activeCamera === 1 ||
                      vars.activeCamera === undefined ? props.camera1 :
                      vars.activeCamera === 2 ? props.camera2 :
                      vars.activeCamera === 3 ? props.camera3 :
                      vars.activeCamera === 4 ? props.camera4 :
                      vars.activeCamera === 5 ? props.camera5 :
                      vars.activeCamera === 6 ? props.camera6 :
                      vars.activeCamera === 7 ? props.camera7 : props.camera1) +
                      '_MP4_History_Length'].state > 0"
                - component: f7-badge
                  config:
                    color: red
                    style:
                      border-radius: 50%
                      height: 20px
                      left: 50%
                      position: absolute
                      top: 5px
                      transform: translateX(-50%)
                      width: 12px
                      z-index: 3
                    visible: "= items[(vars.activeCamera === 1 || vars.activeCamera === undefined ?
                      props.camera1 : vars.activeCamera === 2 ? props.camera2 :
                      vars.activeCamera === 3 ? props.camera3 :
                      vars.activeCamera === 4 ? props.camera4 :
                      vars.activeCamera === 5 ? props.camera5 :
                      vars.activeCamera === 6 ? props.camera6 :
                      vars.activeCamera === 7 ? props.camera7 : props.camera1) +
                      '_MP4_Recording'].state !== NULL &&
                      items[(vars.activeCamera === 1 || vars.activeCamera ===
                      undefined ? props.camera1 : vars.activeCamera === 2 ?
                      props.camera2 : vars.activeCamera === 3 ? props.camera3 :
                      vars.activeCamera === 4 ? props.camera4 :
                      vars.activeCamera === 5 ? props.camera5 :
                      vars.activeCamera === 6 ? props.camera6 :
                      vars.activeCamera === 7 ? props.camera7 : props.camera1) +
                      '_MP4_Recording'].state > 0 && vars.archive !== 2"
    - component: f7-block
      config:
        style:
          background: var(--f7-theme-color)
          border-radius: 0px
          margin: 0
          padding: 8px 15px 15px 15px
          position: relative
        visible: =vars.archive !== 2 && ((vars.activeCamera === 1 || vars.activeCamera
          === undefined) && (!!props.camera1PtzPresetItem ||
          !!props.camera1PtzAutoResetItem) || vars.activeCamera === 2 &&
          (!!props.camera2PtzPresetItem || !!props.camera2PtzAutoResetItem) ||
          vars.activeCamera === 3 && (!!props.camera3PtzPresetItem ||
          !!props.camera3PtzAutoResetItem) || vars.activeCamera === 4 &&
          (!!props.camera4PtzPresetItem || !!props.camera4PtzAutoResetItem) ||
          vars.activeCamera === 5 && (!!props.camera5PtzPresetItem ||
          !!props.camera5PtzAutoResetItem) || vars.activeCamera === 6 &&
          (!!props.camera6PtzPresetItem || !!props.camera6PtzAutoResetItem) ||
          vars.activeCamera === 7 && (!!props.camera7PtzPresetItem ||
          !!props.camera7PtzAutoResetItem))
      slots:
        default:
          - component: f7-row
            config:
              style:
                align-items: center
                height: 40px
                justify-content: center
                margin-bottom: 5px
            slots:
              default:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: ptzExpanded
                    actionVariableValue: "=vars.ptzExpanded === 'true' ? 'false' : 'true'"
                    style:
                      --f7-button-bg-color: rgba(255,255,255,0.2)
                      --f7-button-border-radius: 50%
                      --f7-button-height: 30px
                      --f7-button-width: 30px
                      align-items: center
                      border: 1px solid rgba(255,255,255,0.3)
                      display: flex
                      justify-content: center
                  slots:
                    default:
                      - component: f7-icon
                        config:
                          f7: "=vars.ptzExpanded === 'true' ? 'chevron_up' : 'chevron_down'"
                          size: 16
                          style:
                            color: white
                            transition: transform 0.3s ease
          - component: f7-block
            config:
              style:
                height: "=vars.ptzExpanded === 'true' ? 'auto' : '0px'"
                margin-bottom: 10px
                opacity: "=vars.ptzExpanded === 'true' ? '1' : '0'"
                overflow: hidden
                transition: all 0.3s ease
              visible: =(vars.activeCamera === 1 || vars.activeCamera === undefined) &&
                !!props.camera1PtzPresetItem || vars.activeCamera === 2 &&
                !!props.camera2PtzPresetItem || vars.activeCamera === 3 &&
                !!props.camera3PtzPresetItem || vars.activeCamera === 4 &&
                !!props.camera4PtzPresetItem || vars.activeCamera === 5 &&
                !!props.camera5PtzPresetItem || vars.activeCamera === 6 &&
                !!props.camera6PtzPresetItem || vars.activeCamera === 7 &&
                !!props.camera7PtzPresetItem
            slots:
              default:
                - component: Label
                  config:
                    style:
                      color: white
                      font-size: 13px
                      font-weight: bold
                      margin-bottom: 6px
                    text: "Kamera-Position:"
                - component: f7-swiper
                  config:
                    params:
                      direction: horizontal
                      freeMode: true
                      mousewheel: true
                      scrollbar:
                        draggable: true
                        el: .swiper-scrollbar
                      slidesPerView: auto
                    style:
                      height: 45px
                  slots:
                    default:
                      - component: f7-swiper-slide
                        config:
                          style:
                            padding: 0 4px
                            width: auto
                        slots:
                          default:
                            - component: oh-button
                              config:
                                action: command
                                actionCommand: "5"
                                actionItem: "= vars.activeCamera === 1 || vars.activeCamera === undefined ?
                                  props.camera1PtzPresetItem : vars.activeCamera
                                  === 2 ? props.camera2PtzPresetItem :
                                  vars.activeCamera === 3 ?
                                  props.camera3PtzPresetItem : vars.activeCamera
                                  === 4 ? props.camera4PtzPresetItem :
                                  vars.activeCamera === 5 ?
                                  props.camera5PtzPresetItem : vars.activeCamera
                                  === 6 ? props.camera6PtzPresetItem :
                                  vars.activeCamera === 7 ?
                                  props.camera7PtzPresetItem :
                                  props.camera1PtzPresetItem"
                                style:
                                  align-items: center
                                  background: rgba(255,255,255,0.2)
                                  border: 1px solid rgba(255,255,255,0.3)
                                  border-radius: 6px
                                  color: white
                                  display: flex
                                  font-size: 12px
                                  font-weight: bold
                                  justify-content: center
                                  min-width: 70px
                                  padding: 6px 10px
                                  text-align: center
                                text: Terrasse
                      - component: f7-swiper-slide
                        config:
                          style:
                            padding: 0 4px
                            width: auto
                        slots:
                          default:
                            - component: oh-button
                              config:
                                action: command
                                actionCommand: "1"
                                actionItem: "= vars.activeCamera === 1 || vars.activeCamera === undefined ?
                                  props.camera1PtzPresetItem : vars.activeCamera
                                  === 2 ? props.camera2PtzPresetItem :
                                  vars.activeCamera === 3 ?
                                  props.camera3PtzPresetItem : vars.activeCamera
                                  === 4 ? props.camera4PtzPresetItem :
                                  vars.activeCamera === 5 ?
                                  props.camera5PtzPresetItem : vars.activeCamera
                                  === 6 ? props.camera6PtzPresetItem :
                                  vars.activeCamera === 7 ?
                                  props.camera7PtzPresetItem :
                                  props.camera1PtzPresetItem"
                                style:
                                  align-items: center
                                  background: rgba(255,255,255,0.2)
                                  border: 1px solid rgba(255,255,255,0.3)
                                  border-radius: 6px
                                  color: white
                                  display: flex
                                  font-size: 12px
                                  font-weight: bold
                                  justify-content: center
                                  min-width: 70px
                                  padding: 6px 10px
                                  text-align: center
                                text: Garten
                      - component: f7-swiper-slide
                        config:
                          style:
                            padding: 0 4px
                            width: auto
                        slots:
                          default:
                            - component: oh-button
                              config:
                                action: command
                                actionCommand: "4"
                                actionItem: "= vars.activeCamera === 1 || vars.activeCamera === undefined ?
                                  props.camera1PtzPresetItem : vars.activeCamera
                                  === 2 ? props.camera2PtzPresetItem :
                                  vars.activeCamera === 3 ?
                                  props.camera3PtzPresetItem : vars.activeCamera
                                  === 4 ? props.camera4PtzPresetItem :
                                  vars.activeCamera === 5 ?
                                  props.camera5PtzPresetItem : vars.activeCamera
                                  === 6 ? props.camera6PtzPresetItem :
                                  vars.activeCamera === 7 ?
                                  props.camera7PtzPresetItem :
                                  props.camera1PtzPresetItem"
                                style:
                                  align-items: center
                                  background: rgba(255,255,255,0.2)
                                  border: 1px solid rgba(255,255,255,0.3)
                                  border-radius: 6px
                                  color: white
                                  display: flex
                                  font-size: 12px
                                  font-weight: bold
                                  justify-content: center
                                  min-width: 70px
                                  padding: 6px 10px
                                  text-align: center
                                text: Gartentür
                      - component: f7-swiper-slide
                        config:
                          style:
                            padding: 0 4px
                            width: auto
                        slots:
                          default:
                            - component: oh-button
                              config:
                                action: command
                                actionCommand: "3"
                                actionItem: "= vars.activeCamera === 1 || vars.activeCamera === undefined ?
                                  props.camera1PtzPresetItem : vars.activeCamera
                                  === 2 ? props.camera2PtzPresetItem :
                                  vars.activeCamera === 3 ?
                                  props.camera3PtzPresetItem : vars.activeCamera
                                  === 4 ? props.camera4PtzPresetItem :
                                  vars.activeCamera === 5 ?
                                  props.camera5PtzPresetItem : vars.activeCamera
                                  === 6 ? props.camera6PtzPresetItem :
                                  vars.activeCamera === 7 ?
                                  props.camera7PtzPresetItem :
                                  props.camera1PtzPresetItem"
                                style:
                                  align-items: center
                                  background: rgba(255,255,255,0.2)
                                  border: 1px solid rgba(255,255,255,0.3)
                                  border-radius: 6px
                                  color: white
                                  display: flex
                                  font-size: 12px
                                  font-weight: bold
                                  justify-content: center
                                  min-width: 80px
                                  padding: 6px 10px
                                  text-align: center
                                text: Mähroboter
                      - component: f7-swiper-slide
                        config:
                          style:
                            padding: 0 4px
                            width: auto
                        slots:
                          default:
                            - component: oh-button
                              config:
                                action: command
                                actionCommand: "6"
                                actionItem: "= vars.activeCamera === 1 || vars.activeCamera === undefined ?
                                  props.camera1PtzPresetItem : vars.activeCamera
                                  === 2 ? props.camera2PtzPresetItem :
                                  vars.activeCamera === 3 ?
                                  props.camera3PtzPresetItem : vars.activeCamera
                                  === 4 ? props.camera4PtzPresetItem :
                                  vars.activeCamera === 5 ?
                                  props.camera5PtzPresetItem : vars.activeCamera
                                  === 6 ? props.camera6PtzPresetItem :
                                  vars.activeCamera === 7 ?
                                  props.camera7PtzPresetItem :
                                  props.camera1PtzPresetItem"
                                style:
                                  align-items: center
                                  background: rgba(255,255,255,0.2)
                                  border: 1px solid rgba(255,255,255,0.3)
                                  border-radius: 6px
                                  color: white
                                  display: flex
                                  font-size: 12px
                                  font-weight: bold
                                  justify-content: center
                                  min-width: 80px
                                  padding: 6px 10px
                                  text-align: center
                                text: Ahornbeet
                      - component: f7-swiper-slide
                        config:
                          style:
                            padding: 0 4px
                            width: auto
                        slots:
                          default:
                            - component: oh-button
                              config:
                                action: command
                                actionCommand: "2"
                                actionItem: "= vars.activeCamera === 1 || vars.activeCamera === undefined ?
                                  props.camera1PtzPresetItem : vars.activeCamera
                                  === 2 ? props.camera2PtzPresetItem :
                                  vars.activeCamera === 3 ?
                                  props.camera3PtzPresetItem : vars.activeCamera
                                  === 4 ? props.camera4PtzPresetItem :
                                  vars.activeCamera === 5 ?
                                  props.camera5PtzPresetItem : vars.activeCamera
                                  === 6 ? props.camera6PtzPresetItem :
                                  vars.activeCamera === 7 ?
                                  props.camera7PtzPresetItem :
                                  props.camera1PtzPresetItem"
                                style:
                                  align-items: center
                                  background: rgba(255,255,255,0.2)
                                  border: 1px solid rgba(255,255,255,0.3)
                                  border-radius: 6px
                                  color: white
                                  display: flex
                                  font-size: 12px
                                  font-weight: bold
                                  justify-content: center
                                  min-width: 70px
                                  padding: 6px 10px
                                  text-align: center
                                text: Freisitz
                      - component: f7-swiper-slide
                        config:
                          style:
                            padding: 0 4px
                            width: auto
                        slots:
                          default:
                            - component: oh-button
                              config:
                                action: command
                                actionCommand: "7"
                                actionItem: "= vars.activeCamera === 1 || vars.activeCamera === undefined ?
                                  props.camera1PtzPresetItem : vars.activeCamera
                                  === 2 ? props.camera2PtzPresetItem :
                                  vars.activeCamera === 3 ?
                                  props.camera3PtzPresetItem : vars.activeCamera
                                  === 4 ? props.camera4PtzPresetItem :
                                  vars.activeCamera === 5 ?
                                  props.camera5PtzPresetItem : vars.activeCamera
                                  === 6 ? props.camera6PtzPresetItem :
                                  vars.activeCamera === 7 ?
                                  props.camera7PtzPresetItem :
                                  props.camera1PtzPresetItem"
                                style:
                                  align-items: center
                                  background: rgba(255,255,255,0.2)
                                  border: 1px solid rgba(255,255,255,0.3)
                                  border-radius: 6px
                                  color: white
                                  display: flex
                                  font-size: 12px
                                  font-weight: bold
                                  justify-content: center
                                  min-width: 70px
                                  padding: 6px 10px
                                  text-align: center
                                text: O. Rasen
                      - component: f7-swiper-slide
                        config:
                          style:
                            padding: 0 4px
                            width: auto
                        slots:
                          default:
                            - component: oh-button
                              config:
                                action: command
                                actionCommand: "8"
                                actionItem: "= vars.activeCamera === 1 || vars.activeCamera === undefined ?
                                  props.camera1PtzPresetItem : vars.activeCamera
                                  === 2 ? props.camera2PtzPresetItem :
                                  vars.activeCamera === 3 ?
                                  props.camera3PtzPresetItem : vars.activeCamera
                                  === 4 ? props.camera4PtzPresetItem :
                                  vars.activeCamera === 5 ?
                                  props.camera5PtzPresetItem : vars.activeCamera
                                  === 6 ? props.camera6PtzPresetItem :
                                  vars.activeCamera === 7 ?
                                  props.camera7PtzPresetItem :
                                  props.camera1PtzPresetItem"
                                style:
                                  align-items: center
                                  background: rgba(255,255,255,0.2)
                                  border: 1px solid rgba(255,255,255,0.3)
                                  border-radius: 6px
                                  color: white
                                  display: flex
                                  font-size: 12px
                                  font-weight: bold
                                  justify-content: center
                                  min-width: 70px
                                  padding: 6px 10px
                                  text-align: center
                                text: Balkon
                      - component: f7-swiper-slide
                        config:
                          style:
                            padding: 0 4px
                            width: auto
                        slots:
                          default:
                            - component: oh-button
                              config:
                                action: command
                                actionCommand: "9"
                                actionItem: "= vars.activeCamera === 1 || vars.activeCamera === undefined ?
                                  props.camera1PtzPresetItem : vars.activeCamera
                                  === 2 ? props.camera2PtzPresetItem :
                                  vars.activeCamera === 3 ?
                                  props.camera3PtzPresetItem : vars.activeCamera
                                  === 4 ? props.camera4PtzPresetItem :
                                  vars.activeCamera === 5 ?
                                  props.camera5PtzPresetItem : vars.activeCamera
                                  === 6 ? props.camera6PtzPresetItem :
                                  vars.activeCamera === 7 ?
                                  props.camera7PtzPresetItem :
                                  props.camera1PtzPresetItem"
                                style:
                                  align-items: center
                                  background: rgba(255,255,255,0.2)
                                  border: 1px solid rgba(255,255,255,0.3)
                                  border-radius: 6px
                                  color: white
                                  display: flex
                                  font-size: 12px
                                  font-weight: bold
                                  justify-content: center
                                  min-width: 110px
                                  padding: 6px 10px
                                  text-align: center
                                text: Haus und Dach
          - component: f7-block
            config:
              style:
                height: "=vars.ptzExpanded === 'true' ? 'auto' : '0px'"
                opacity: "=vars.ptzExpanded === 'true' ? '1' : '0'"
                overflow: hidden
                transition: all 0.3s ease
              visible: =(vars.activeCamera === 1 || vars.activeCamera === undefined) &&
                !!props.camera1PtzAutoResetItem || vars.activeCamera === 2 &&
                !!props.camera2PtzAutoResetItem || vars.activeCamera === 3 &&
                !!props.camera3PtzAutoResetItem || vars.activeCamera === 4 &&
                !!props.camera4PtzAutoResetItem || vars.activeCamera === 5 &&
                !!props.camera5PtzAutoResetItem || vars.activeCamera === 6 &&
                !!props.camera6PtzAutoResetItem || vars.activeCamera === 7 &&
                !!props.camera7PtzAutoResetItem
            slots:
              default:
                - component: Label
                  config:
                    style:
                      color: white
                      font-size: 13px
                      font-weight: bold
                      margin-bottom: 6px
                    text: "PTZ-Modus:"
                - component: f7-row
                  config:
                    style:
                      gap: 6px
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: command
                          actionCommand: "1"
                          actionItem: "= vars.activeCamera === 1 || vars.activeCamera === undefined ?
                            props.camera1PtzAutoResetItem : vars.activeCamera
                            === 2 ? props.camera2PtzAutoResetItem :
                            vars.activeCamera === 3 ?
                            props.camera3PtzAutoResetItem : vars.activeCamera
                            === 4 ? props.camera4PtzAutoResetItem :
                            vars.activeCamera === 5 ?
                            props.camera5PtzAutoResetItem : vars.activeCamera
                            === 6 ? props.camera6PtzAutoResetItem :
                            vars.activeCamera === 7 ?
                            props.camera7PtzAutoResetItem :
                            props.camera1PtzAutoResetItem"
                          style:
                            align-items: center
                            background: rgba(255,255,255,0.2)
                            border: 1px solid rgba(255,255,255,0.3)
                            border-radius: 6px
                            color: white
                            display: flex
                            flex: 1
                            font-size: 12px
                            font-weight: bold
                            justify-content: center
                            padding: 8px
                            text-align: center
                          text: Auto-Reset
                      - component: oh-button
                        config:
                          action: command
                          actionCommand: "2"
                          actionItem: "= vars.activeCamera === 1 || vars.activeCamera === undefined ?
                            props.camera1PtzAutoResetItem : vars.activeCamera
                            === 2 ? props.camera2PtzAutoResetItem :
                            vars.activeCamera === 3 ?
                            props.camera3PtzAutoResetItem : vars.activeCamera
                            === 4 ? props.camera4PtzAutoResetItem :
                            vars.activeCamera === 5 ?
                            props.camera5PtzAutoResetItem : vars.activeCamera
                            === 6 ? props.camera6PtzAutoResetItem :
                            vars.activeCamera === 7 ?
                            props.camera7PtzAutoResetItem :
                            props.camera1PtzAutoResetItem"
                          style:
                            align-items: center
                            background: rgba(255,255,255,0.2)
                            border: 1px solid rgba(255,255,255,0.3)
                            border-radius: 6px
                            color: white
                            display: flex
                            flex: 1
                            font-size: 12px
                            font-weight: bold
                            justify-content: center
                            padding: 8px
                            text-align: center
                          text: Kamerafahrt
                      - component: oh-button
                        config:
                          action: command
                          actionCommand: "3"
                          actionItem: "= vars.activeCamera === 1 || vars.activeCamera === undefined ?
                            props.camera1PtzAutoResetItem : vars.activeCamera
                            === 2 ? props.camera2PtzAutoResetItem :
                            vars.activeCamera === 3 ?
                            props.camera3PtzAutoResetItem : vars.activeCamera
                            === 4 ? props.camera4PtzAutoResetItem :
                            vars.activeCamera === 5 ?
                            props.camera5PtzAutoResetItem : vars.activeCamera
                            === 6 ? props.camera6PtzAutoResetItem :
                            vars.activeCamera === 7 ?
                            props.camera7PtzAutoResetItem :
                            props.camera1PtzAutoResetItem"
                          style:
                            align-items: center
                            background: rgba(255,255,255,0.2)
                            border: 1px solid rgba(255,255,255,0.3)
                            border-radius: 6px
                            color: white
                            display: flex
                            flex: 1
                            font-size: 12px
                            font-weight: bold
                            justify-content: center
                            padding: 8px
                            text-align: center
                          text: Manuell
    - component: f7-block
      config:
        style:
          background: var(--f7-theme-color)
          border-radius: 0px
          margin: 0
          padding: 8px 15px
        visible: =vars.archive === 2 || !((vars.activeCamera === 1 || vars.activeCamera
          === undefined) && (!!props.camera1PtzPresetItem ||
          !!props.camera1PtzAutoResetItem) || vars.activeCamera === 2 &&
          (!!props.camera2PtzPresetItem || !!props.camera2PtzAutoResetItem) ||
          vars.activeCamera === 3 && (!!props.camera3PtzPresetItem ||
          !!props.camera3PtzAutoResetItem) || vars.activeCamera === 4 &&
          (!!props.camera4PtzPresetItem || !!props.camera4PtzAutoResetItem) ||
          vars.activeCamera === 5 && (!!props.camera5PtzPresetItem ||
          !!props.camera5PtzAutoResetItem) || vars.activeCamera === 6 &&
          (!!props.camera6PtzPresetItem || !!props.camera6PtzAutoResetItem) ||
          vars.activeCamera === 7 && (!!props.camera7PtzPresetItem ||
          !!props.camera7PtzAutoResetItem))
      slots:
        default:
          - component: Label
            config:
              style:
                display: block
                height: 1px
              text: ""
    - component: f7-popup
      config:
        backdrop: true
        closeByBackdropClick: true
        closeByOutsideClick: true
        closeOnEscape: true
        id: fullscreenCamera
        opened: =vars.fullscreenOpen === 'true'
        style:
          background: black
          z-index: 10000
      slots:
        default:
          - component: f7-block
            config:
              style:
                align-items: center
                background: black
                display: flex
                height: 100vh
                justify-content: center
                margin: 0
                padding: 0
                position: relative
                width: 100vw
            slots:
              default:
                - component: oh-image-card
                  config:
                    item: "= vars.activeCamera === 1 || vars.activeCamera === undefined ?
                      props.camera1ImageItem : vars.activeCamera === 2 ?
                      props.camera2ImageItem : vars.activeCamera === 3 ?
                      props.camera3ImageItem : vars.activeCamera === 4 ?
                      props.camera4ImageItem : vars.activeCamera === 5 ?
                      props.camera5ImageItem : vars.activeCamera === 6 ?
                      props.camera6ImageItem : vars.activeCamera === 7 ?
                      props.camera7ImageItem : props.camera1ImageItem"
                    noBorder: true
                    noShadow: true
                    refreshInterval: =props.refreshRate
                    style:
                      background: transparent
                      height: 100%
                      object-fit: contain
                      width: 100%
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: fullscreenOpen
                    actionVariableValue: "false"
                    iconColor: red
                    iconF7: xmark
                    iconSize: 28
                    style:
                      height: 32px
                      margin: -2px
                      position: absolute
                      right: 0px
                      top: 0px
                      width: 32px
                      z-index: 10001

You’re running up against the inherent limitations of the OH widget and f7 systems. I don’t think there’s a built-in way for you to do this. This is probably possible if you are really determined but it will almost definitely require some un-official javascript methods (see this topic).

You certainly cannot easily add the ability to zoom to any widget that does not already have that capability because the setting of the main OH page deactivates basic browser zoom actions. So, it would require significant custom js scripting to add that feature individually to elements.

If there is any remotely reasonable path to this at all, it would be through a simple script that forces the f7 photo browser to refresh the image. You might even able to combine this with something like this so you wouldn’t have worry about creating and destroying your own js timer intervals.

Honestly, if I were trying to create something like this, I would take 1 of 2 paths: 1) Create a quick independent web app that then is just loaded in an oh-webframe (maybe an LLM can even get you most of the way there pretty quickly at this point, I don’t know), or 2) create a PR for the oh webui that adds a refresh interval as a possible configuration to the photos action.

Thanks for the explanation!

I think I’ll go with option 2 and try to create a PR for the OH WebUI to add a refresh interval to the photos action.

I haven’t done a PR before, but I’m willing to give it a try.

Update: I’ve made some changes to add a refresh interval for the photos action, but I don’t have a test environment, so I can’t verify if it works. I would really appreciate it if someone with a working setup could try it and give feedback.

I don’t see your PR on the webui repo. If you have only created a version on your own fork and not submitted it is as a PR yet, then you’ll have to share a link to that fork and branch if others are going to test it for you.

But, even better, you can also submit it as a PR even if it’s not finished. Just label it as [WIP] (work in progress), and then anyone looking at the main repo site will be able to see it and give feedback, including the maintainers who will give you the most valuable feedback (including whether this is a PR that is likely to be approved at all or conflicts with some design goal or UI philosophy - a rare but not impossible occurrence).

Oops — looks like I messed this up a bit — my first PR attempt :sweat_smile:

I originally had the changes split into my own fork’s branches (patch-1 and patch-2) and hadn’t opened a PR. But I’ve now merged everything into a single branch and created a proper [WIP] Pull Request here:
https://github.com/openhab/openhab-webui/pull/3332

Would you mind taking another look now? I’d really appreciate any feedback — especially since I don’t yet have a test environment and the maintainers’ input will be especially valuable.

Thanks in advance!