diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9b01e35..9db7949 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -79,6 +79,7 @@ set(SOURCE_FILES
     inc/spkstretchlayout.h gui/spkstretchlayout.cpp
     inc/spkfocuslineedit.h
     inc/spknotifydot.h gui/spknotifydot.cpp
+    inc/spkimgviewer.h gui/spkimgviewer.cpp
 
     inc/page/spkpagebase.h gui/page/spkpagebase.cpp
     inc/page/spkpagehome.h gui/page/spkpagehome.cpp
diff --git a/gui/page/spkpageappdetails.cpp b/gui/page/spkpageappdetails.cpp
index eba6e92..1559afd 100644
--- a/gui/page/spkpageappdetails.cpp
+++ b/gui/page/spkpageappdetails.cpp
@@ -23,31 +23,59 @@ namespace SpkUi
                                        Qt::SmoothTransformation));
       else
       {
-        mAppIcon->setPixmap(QIcon(":/icons/broken-icon.svg").pixmap(IconSize));
+        mAppIcon->setPixmap(mBrokenImg);
         RES->PurgeCachedResource(aPkgName, SpkResource::ResourceType::AppIcon, 0);
       }
     }
 
-    // Load screenshots
+    // Load screenshots. Screenshots have id starting with 1.
     if(aScreenshots.isEmpty())
       return;
+    else
+    {
+      auto count = aScreenshots.size();
+      mImgViewer->SetImageTotal(count);
+      if(count > mScreenshotPreviews.size())
+      {
+        auto from = mScreenshotPreviews.size(), to = count - mScreenshotPreviews.size();
+        for(int i = 0; i <= to; i++)
+        {
+          auto wid = new SpkClickLabel;
+          wid->setProperty("shotId", from + i + 1);
+          wid->setFixedHeight(200);
+          wid->setCursor(Qt::PointingHandCursor);
+          connect(wid, &SpkClickLabel::Pressed, this, &SpkPageAppDetails::ImageClicked);
+          mScreenshotPreviews.append(wid);
+          mScreenshotLay->addWidget(wid);
+        }
+      }
+    }
 
     int shotId = 0;
     for(auto &i : aScreenshots)
     {
       shotId++;
-      res = RES->RequestResource(shotId, aPkgName, SpkResource::ResourceType::AppScreenshot, aIcon,
+      res = RES->RequestResource(shotId, aPkgName, SpkResource::ResourceType::AppScreenshot, i,
                                  shotId);
+      auto preview = mScreenshotPreviews[shotId - 1];
+      preview->setVisible(true);
       if(res.status == SpkResource::ResourceStatus::Ready)
       {
         if(pic.loadFromData(res.data))
-          ;// TODO
-          else
-          {
-            // TODO
-            //        mAppIcon->setPixmap(QIcon(":/icons/broken-icon.svg").pixmap(SpkAppItem::IconSize_));
-            RES->PurgeCachedResource(aPkgName, SpkResource::ResourceType::AppScreenshot, 0);
-          }
+        {
+          mAppImages[shotId] = pic;
+          mImgViewer->SetPixmap(shotId, &mAppImages[shotId]);
+          preview->setPixmap(pic.scaledToHeight(200, Qt::SmoothTransformation));
+        }
+        else
+        {
+          mAppImages[shotId] = mBrokenImg;
+          RES->PurgeCachedResource(aPkgName, SpkResource::ResourceType::AppScreenshot, 0);
+        }
+      }
+      else
+      {
+        preview->setPixmap(mIconLoading);
       }
     }
 
@@ -64,7 +92,9 @@ namespace SpkUi
     mPkgPath = url;
   }
 
-  SpkPageAppDetails::SpkPageAppDetails(QWidget *parent) : SpkPageBase(parent)
+  SpkPageAppDetails::SpkPageAppDetails(QWidget *parent) : SpkPageBase(parent),
+    mBrokenImg(QIcon(":/icons/broken-icon.svg").pixmap(SpkAppItem::IconSize_)),
+    mIconLoading(QIcon(":/icons/loading-icon.svg").pixmap(SpkAppItem::IconSize_))
   {
     mMainArea = new QScrollArea;
     mMainArea->setWidgetResizable(true);
@@ -148,6 +178,18 @@ namespace SpkUi
     mDetailsLay->addLayout(mDetailLay);
     mDetailsLay->addWidget(mAppDescription);
 //    mMainLay->addStretch();
+
+    mScreenshotLay = new QHBoxLayout;
+    mScreenshotArea = new QScrollArea;
+    mWid4ShotArea = new QWidget;
+    mWid4ShotArea->setLayout(mScreenshotLay);
+    mScreenshotArea->setWidget(mWid4ShotArea);
+    mScreenshotArea->setWidgetResizable(true);
+    mScreenshotArea->setFixedHeight(230);
+    mScreenshotArea->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
+
+    mDetailsLay->addWidget(mScreenshotArea);
+
     mWid4MainArea = new QWidget;
     mWid4MainArea->setLayout(mDetailsLay);
 
@@ -182,43 +224,80 @@ namespace SpkUi
     mBottomBarLay->addWidget(mBtnRequestUpdate);
     mBottomBarLay->addWidget(mBtnReport);
 
+    mImgViewer = new SpkImgViewer;
+    mImgViewer->setVisible(false);
+
     connect(mBtnDownload, &QPushButton::clicked,
             [=](){ emit RequestDownload(mAppTitle->text(), mPkgName->text(),
                                         "/store/reading/youdao-dict/youdao-dict_6.0.0-0~ubuntu_amd64.deb");
-                 });
+    });
+  }
+
+  SpkPageAppDetails::~SpkPageAppDetails()
+  {
+    delete mImgViewer;
   }
 
   void SpkPageAppDetails::ResourceAcquisitionFinished(int id, ResourceResult result)
   {
-    QPixmap icon;
+    QPixmap img;
 //    qDebug() << "PageAppDetails: Resource" << id << "acquired";
     if(!id)
     {
       // id == 0, icon
       if(result.status == SpkResource::ResourceStatus::Ready)
       {
-        if(icon.loadFromData(result.data))
-          mAppIcon->setPixmap(icon.scaled(SpkAppItem::IconSize_,
+        if(img.loadFromData(result.data))
+          mAppIcon->setPixmap(img.scaled(SpkAppItem::IconSize_,
                                           Qt::IgnoreAspectRatio,
                                           Qt::SmoothTransformation));
         else
-          mAppIcon->setPixmap(QIcon(":/icons/broken-icon.svg").pixmap(SpkAppItem::IconSize_));
+          mAppIcon->setPixmap(mBrokenImg);
       }
       else if(result.status == SpkResource::ResourceStatus::Failed)
       {
-        mAppIcon->setPixmap(QIcon(":/icons/broken-icon.svg").pixmap(SpkAppItem::IconSize_));
+        mAppIcon->setPixmap(mBrokenImg);
         RES->PurgeCachedResource(mPkgName->text(), SpkResource::ResourceType::AppIcon, 0);
       }
     }
     else
     {
-      // TODO: screenshots
+      auto preview = mScreenshotPreviews[id - 1];
+      preview->setVisible(true);
+      if(result.status == SpkResource::ResourceStatus::Ready)
+      {
+        if(img.loadFromData(result.data))
+        {
+          mAppImages[id] = img;
+          mImgViewer->SetPixmap(id, &mAppImages[id]);
+          mScreenshotPreviews[id - 1]->setPixmap(img.scaledToHeight(200, Qt::SmoothTransformation));
+        }
+        else
+        {
+          mImgViewer->SetPixmap(id, &mBrokenImg);
+          mScreenshotPreviews[id - 1]->setPixmap(mBrokenImg);
+        }
+      }
+      else if(result.status == SpkResource::ResourceStatus::Failed)
+      {
+        mImgViewer->SetPixmap(id, &mBrokenImg);
+        mScreenshotPreviews[id - 1]->setPixmap(mBrokenImg);
+        RES->PurgeCachedResource(mPkgName->text(), SpkResource::ResourceType::AppIcon, 0);
+      }
     }
   }
 
   void SpkPageAppDetails::Activated()
   {
     RES->Acquire(this, false);
+    for(auto &i : mScreenshotPreviews)
+      i->setVisible(false);
+    mImgViewer->Clear();
+  }
+
+  void SpkPageAppDetails::ImageClicked()
+  {
+    mImgViewer->ShowWithImage(sender()->property("shotId").toInt());
   }
 
   SpkDetailEntry::SpkDetailEntry(QWidget *parent) : QWidget(parent)
diff --git a/gui/spkimgviewer.cpp b/gui/spkimgviewer.cpp
new file mode 100644
index 0000000..db1c657
--- /dev/null
+++ b/gui/spkimgviewer.cpp
@@ -0,0 +1,120 @@
+
+#include "spktitlebar.h"
+#include "spkimgviewer.h"
+#include "spkui_general.h"
+#include <QDebug>
+#include <QFocusEvent>
+#include <QGuiApplication>
+#include <QScreen>
+
+SpkImgViewer::SpkImgViewer(QWidget *parent) :
+  SpkWindow(parent),
+  mIconLoading(QIcon(":/icons/loading-icon.svg").pixmap({ 72, 72 }))
+{
+  mImgIndict = new QLabel;
+  mImgIndict->setText("%1/%2");
+  mBtnPrev = new QPushButton;
+  mBtnPrev->setText("<");
+  mBtnNext = new QPushButton;
+  mBtnNext->setText(">");
+
+  auto titleBar = GetTitleBar();
+  titleBar->SetUseIcon(false);
+  titleBar->SetTitle(tr("Image Preview"));
+  titleBar->SetOperationButton(SpkTitleBar::OperationButton::Close);
+
+  auto lay = titleBar->GetUserSpace();
+  lay->setAlignment(Qt::AlignVCenter);
+  lay->addStretch();
+  lay->addWidget(mBtnPrev);
+  lay->addWidget(mImgIndict);
+  lay->addWidget(mBtnNext);
+  lay->addStretch();
+
+  mImgArea = new QScrollArea;
+  mImgArea->setWidgetResizable(true);
+  mImgArea->setContentsMargins(10, 10, 10, 10);
+
+  mImgShow = new ImgView;
+
+  mImgArea->setWidget(mImgShow);
+
+  auto w = new QWidget;
+  auto l = new QHBoxLayout;
+  l->setContentsMargins(10, 10, 10, 10);
+  l->addWidget(mImgArea);
+  w->setLayout(l);
+  SetCentralWidget(w);
+
+  connect(mBtnPrev, &QPushButton::clicked,
+          [&](){ if(mCurrentImg > 0) { SwitchToImage(--mCurrentImg); } });
+  connect(mBtnNext, &QPushButton::clicked,
+          [&](){ if(mCurrentImg < mTotalImg) { SwitchToImage(++mCurrentImg); } });
+}
+
+void SpkImgViewer::ShowWithImage(int idx)
+{
+  SwitchToImage(idx);
+  show();
+}
+
+void SpkImgViewer::Clear()
+{
+  mImgMap.clear();
+  mImgShow->SetPixmap(nullptr);
+  mCurrentImg = 1;
+}
+
+void SpkImgViewer::SetPixmap(int idx, QPixmap *img)
+{
+  mImgMap[idx] = img;
+  if(mCurrentImg == idx)
+  {
+    mImgShow->SetPixmap(img);
+  }
+  ResizeToFitImageSize(img->size());
+}
+
+void SpkImgViewer::SwitchToImage(int idx)
+{
+  auto img = mImgMap.value(idx, nullptr);
+  mCurrentImg = idx;
+  mImgShow->SetPixmap(img ? img : &mIconLoading);
+  if(img)
+    ResizeToFitImageSize(img->size());
+  if(idx == 1)
+  {
+    mBtnPrev->setEnabled(false);
+    mBtnNext->setEnabled(true);
+  }
+  else if(idx == mTotalImg)
+  {
+    mBtnPrev->setEnabled(true);
+    mBtnNext->setEnabled(false);
+  }
+  else
+  {
+    mBtnPrev->setEnabled(true);
+    mBtnNext->setEnabled(true);
+  }
+  mImgIndict->setText(QString("%1/%2").arg(mCurrentImg).arg(mTotalImg));
+}
+
+bool SpkImgViewer::event(QEvent *e)
+{
+  if(e->type() == QEvent::WindowDeactivate)
+    close();
+  return SpkWindow::event(e);
+}
+
+void SpkImgViewer::ResizeToFitImageSize(QSize s)
+{
+  auto targetSize = s;
+  targetSize.rheight() += SpkTitleBar::Height;
+  targetSize = s.grownBy(QMargins(10, 10, 10, 10));
+  targetSize = targetSize.boundedTo(SpkUi::PrimaryScreenSize * 0.8);
+  resize(targetSize);
+  targetSize /= 2;
+  auto targetPos = SpkUi::PrimaryScreenSize / 2 - targetSize;
+  move(targetPos.width(), targetPos.height());
+}
diff --git a/gui/spktitlebar.cpp b/gui/spktitlebar.cpp
index 7a72020..69dfd11 100644
--- a/gui/spktitlebar.cpp
+++ b/gui/spktitlebar.cpp
@@ -9,8 +9,7 @@ SpkTitleBar::SpkTitleBar(QWidget *parent) : QFrame(parent)
 {
   mLinkedWindow = nullptr;
 
-  setMinimumHeight(48);
-  setMaximumHeight(48);
+  setFixedHeight(Height);
   setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
 
   mIcon = new QLabel(this);
diff --git a/inc/page/spkpageappdetails.h b/inc/page/spkpageappdetails.h
index 76f7f18..948b1a6 100644
--- a/inc/page/spkpageappdetails.h
+++ b/inc/page/spkpageappdetails.h
@@ -8,16 +8,27 @@
 #include <QFormLayout>
 #include "page/spkpagebase.h"
 #include "spkstretchlayout.h"
+#include "spkimgviewer.h"
 
 namespace SpkUi
 {
   class SpkDetailEntry;
 
+  class SpkClickLabel : public QLabel
+  {
+      Q_OBJECT
+    protected:
+      virtual void mousePressEvent(QMouseEvent *e) override { emit Pressed(); }
+    signals:
+      void Pressed();
+  };
+
   class SpkPageAppDetails : public SpkPageBase
   {
       Q_OBJECT
     public:
       SpkPageAppDetails(QWidget *parent = nullptr);
+      ~SpkPageAppDetails();
 
       void LoadAppResources(QString pkgName, QString icon, QStringList screenshots, QStringList tags);
       void SetWebsiteLink(QString url);
@@ -25,6 +36,7 @@ namespace SpkUi
 
     private:
       QString mPkgPath;
+      QPixmap mBrokenImg, mIconLoading;
 
     public slots:
       void ResourceAcquisitionFinished(int id, ResourceResult result);
@@ -34,14 +46,18 @@ namespace SpkUi
       static constexpr QSize IconSize { 144, 144 };
 
       // Main Area
-      QScrollArea *mMainArea;
-      QWidget *mDetailWidget, *mIconTitleWidget, *mWid4MainArea;
+      QScrollArea *mMainArea, *mScreenshotArea;
+      QWidget *mDetailWidget, *mIconTitleWidget, *mWid4MainArea, *mWid4ShotArea;
       QLabel *mAppTitle, *mAppIcon, *mAppDescription, *mAppShortDesc, *mPkgName, *mVersion,
              *mWebsite;
       SpkDetailEntry *mAuthor, *mContributor, *mSite, *mArch, *mSize;
       SpkStretchLayout *mDetailLay;
       QVBoxLayout *mDetailsLay, *mTitleLay, *mMainLay;
-      QHBoxLayout *mIconTitleLay;
+      QHBoxLayout *mIconTitleLay, *mScreenshotLay;
+      QList<SpkClickLabel*> mScreenshotPreviews;
+
+      QMap<int, QPixmap> mAppImages;
+      SpkImgViewer *mImgViewer;
 
       // Bottom bar
       QWidget *mBottomBar;
@@ -50,6 +66,9 @@ namespace SpkUi
 
     signals:
       void RequestDownload(QString name, QString pkgName, QString path);
+
+    private slots:
+      void ImageClicked();
   };
 
   class SpkDetailEntry : public QWidget
diff --git a/inc/spkimgviewer.h b/inc/spkimgviewer.h
new file mode 100644
index 0000000..4d46756
--- /dev/null
+++ b/inc/spkimgviewer.h
@@ -0,0 +1,61 @@
+
+#pragma once
+
+#include <QPainter>
+#include <QScrollArea>
+#include "spkwindow.h"
+
+class ImgView : public QWidget
+{
+    Q_OBJECT
+
+  public:
+    ImgView(QWidget *parent = nullptr) : QWidget(parent) { mPixmap = nullptr; }
+    void SetPixmap(QPixmap *p) { mPixmap = p; if(p) setFixedSize(p->size()); update(); }
+
+  protected:
+    void paintEvent(QPaintEvent *e)
+    {
+      QPainter p(this);
+      if(mPixmap)
+        p.drawPixmap(0, 0, *mPixmap);
+      p.end();
+      e->accept();
+    }
+
+  private:
+    QPixmap *mPixmap;
+};
+
+class SpkImgViewer : public SpkWindow
+{
+    Q_OBJECT
+
+  public:
+    SpkImgViewer(QWidget *parent = nullptr);
+    void ShowWithImage(int idx);
+    void SetImageTotal(int a) { mTotalImg = a; }
+
+  public slots:
+    void Clear();
+    void SetPixmap(int idx, QPixmap *img);
+
+  private slots:
+    void SwitchToImage(int idx);
+
+  protected:
+    bool event(QEvent*) override;
+
+  private:
+    void ResizeToFitImageSize(QSize);
+
+  private:
+    QPushButton *mBtnPrev, *mBtnNext;
+    QScrollArea *mImgArea;
+    QLabel *mImgIndict;
+    QMap<int, QPixmap*> mImgMap;
+    int mCurrentImg, mTotalImg;
+    QPixmap mIconLoading;
+
+    ImgView *mImgShow;
+};
diff --git a/inc/spktitlebar.h b/inc/spktitlebar.h
index 39288a1..e290b9e 100644
--- a/inc/spktitlebar.h
+++ b/inc/spktitlebar.h
@@ -43,6 +43,7 @@ class SpkTitleBar : public QFrame
   public:
     SpkTitleBar(QWidget *parent = nullptr);
     ~SpkTitleBar();
+    static constexpr int Height = 48;
     using OperationButton = SpkTitleBarDefaultButton::OperationButton;
     void SetOperationButton(OperationButton);
 
diff --git a/lang/zh.ts b/lang/zh.ts
index d606f6b..ca53d7c 100644
--- a/lang/zh.ts
+++ b/lang/zh.ts
@@ -403,6 +403,14 @@ Right now we are not just a Chinese group. We are discovering our way into more
         <translation>关于</translation>
     </message>
 </context>
+<context>
+    <name>SpkImgViewer</name>
+    <message>
+        <location filename="../gui/spkimgviewer.cpp" line="23"/>
+        <source>Image Preview</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
 <context>
     <name>SpkMainWindow</name>
     <message>
@@ -666,47 +674,47 @@ to use terminal for program output.</source>
 <context>
     <name>SpkUi::SpkPageAppDetails</name>
     <message>
-        <location filename="../gui/page/spkpageappdetails.cpp" line="59"/>
+        <location filename="../gui/page/spkpageappdetails.cpp" line="87"/>
         <source>Website link</source>
         <translation>网站链接</translation>
     </message>
     <message>
-        <location filename="../gui/page/spkpageappdetails.cpp" line="124"/>
+        <location filename="../gui/page/spkpageappdetails.cpp" line="154"/>
         <source>Author</source>
         <translation>作者</translation>
     </message>
     <message>
-        <location filename="../gui/page/spkpageappdetails.cpp" line="126"/>
+        <location filename="../gui/page/spkpageappdetails.cpp" line="156"/>
         <source>Contributor</source>
         <translation>贡献者</translation>
     </message>
     <message>
-        <location filename="../gui/page/spkpageappdetails.cpp" line="130"/>
+        <location filename="../gui/page/spkpageappdetails.cpp" line="160"/>
         <source>Architecture</source>
         <translation>架构</translation>
     </message>
     <message>
-        <location filename="../gui/page/spkpageappdetails.cpp" line="132"/>
+        <location filename="../gui/page/spkpageappdetails.cpp" line="162"/>
         <source>Size</source>
         <translation>大小</translation>
     </message>
     <message>
-        <location filename="../gui/page/spkpageappdetails.cpp" line="164"/>
+        <location filename="../gui/page/spkpageappdetails.cpp" line="206"/>
         <source>Download</source>
         <translation>下载</translation>
     </message>
     <message>
-        <location filename="../gui/page/spkpageappdetails.cpp" line="170"/>
+        <location filename="../gui/page/spkpageappdetails.cpp" line="212"/>
         <source>Uninstall</source>
         <translation>卸载</translation>
     </message>
     <message>
-        <location filename="../gui/page/spkpageappdetails.cpp" line="173"/>
+        <location filename="../gui/page/spkpageappdetails.cpp" line="215"/>
         <source>Request Update</source>
         <translation>请求更新</translation>
     </message>
     <message>
-        <location filename="../gui/page/spkpageappdetails.cpp" line="176"/>
+        <location filename="../gui/page/spkpageappdetails.cpp" line="218"/>
         <source>Report</source>
         <translation>举报</translation>
     </message>
diff --git a/src/main.cpp b/src/main.cpp
index efc890f..d87936f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -6,7 +6,7 @@
 #include "spkstore.h"
 
 #include "spkdownload.h"
-#include "spkmsgbox.h"
+#include "spkimgviewer.h"
 
 
 int main(int argc, char *argv[])
@@ -30,21 +30,5 @@ int main(int argc, char *argv[])
 
   SpkStore store(false, LogPath);
 
-//  SpkDownloadMgr dl;
-//  dl.SetNewServers({
-//                     "https://d1.store.deepinos.org.cn/",
-//                     "https://d2.store.deepinos.org.cn/",
-//                     "https://d3.store.deepinos.org.cn/",
-//                     "https://d4.store.deepinos.org.cn/",
-//                     "https://d5.store.deepinos.org.cn/"
-//                   });
-//  dl.SetDestinationFolder("/tmp/");
-//  dl.StartNewDownload("store/office/cn.com.10jqka/cn.com.10jqka_1.6.1.2_amd64.deb", 0);
-//  QObject::connect(&dl, &SpkDownloadMgr::DownloadStopped,
-//                   [&](SpkDownloadMgr::TaskResult, int)
-//  {
-//    SpkMsgBox::StaticExec("Finished", "");
-//  });
-
   return QApplication::exec();
 }